diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/JavaScriptCore/wtf | |
parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/JavaScriptCore/wtf')
53 files changed, 2194 insertions, 670 deletions
diff --git a/Source/JavaScriptCore/wtf/Assertions.h b/Source/JavaScriptCore/wtf/Assertions.h index 42dc0bd35..e7358dccb 100644 --- a/Source/JavaScriptCore/wtf/Assertions.h +++ b/Source/JavaScriptCore/wtf/Assertions.h @@ -322,8 +322,12 @@ while (0) /* COMPILE_ASSERT */ #ifndef COMPILE_ASSERT +#if COMPILER_SUPPORTS(C_STATIC_ASSERT) +#define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name) +#else #define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1] #endif +#endif /* FATAL */ @@ -370,29 +374,4 @@ while (0) #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #endif -#if ENABLE(GC_VALIDATION) -#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \ - if (!(cell))\ - CRASH();\ - if (cell->unvalidatedStructure()->unvalidatedStructure() != cell->unvalidatedStructure()->unvalidatedStructure()->unvalidatedStructure())\ - CRASH();\ -} while (0) - -#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do {\ - ASSERT_GC_OBJECT_LOOKS_VALID(object); \ - if (!object->inherits(classInfo)) \ - CRASH();\ -} while (0) - -#else -#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { (void)cell; } while (0) -#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0) -#endif - -#if COMPILER(CLANG) -#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) COMPILE_ASSERT(__has_trivial_destructor(klass), klass##_has_trivial_destructor_check) -#else -#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) -#endif - #endif /* WTF_Assertions_h */ diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt index c22ae5185..63fc59c73 100644 --- a/Source/JavaScriptCore/wtf/CMakeLists.txt +++ b/Source/JavaScriptCore/wtf/CMakeLists.txt @@ -3,8 +3,6 @@ SET(WTF_HEADERS AVLTree.h Alignment.h AlwaysInline.h - ArrayBuffer.cpp - ArrayBufferView.cpp Assertions.h Atomics.h BitVector.h @@ -17,6 +15,7 @@ SET(WTF_HEADERS CryptographicallyRandomNumber.h CurrentTime.h DateMath.h + DataLog.h DecimalNumber.h Decoder.h Deque.h @@ -45,7 +44,6 @@ SET(WTF_HEADERS MallocZoneSupport.h MathExtras.h MessageQueue.h - MetaAllocator.cpp MetaAllocator.h MetaAllocatorHandle.h NonCopyingSort.h @@ -134,18 +132,22 @@ SET(WTF_HEADERS ) SET(WTF_SOURCES + ArrayBuffer.cpp + ArrayBufferView.cpp Assertions.cpp BitVector.cpp ByteArray.cpp CryptographicallyRandomNumber.cpp CurrentTime.cpp DateMath.cpp + DataLog.cpp DecimalNumber.cpp DynamicAnnotations.cpp FastMalloc.cpp HashTable.cpp - MainThread.cpp MD5.cpp + MainThread.cpp + MetaAllocator.cpp OSRandomSource.cpp NumberOfCores.cpp PageAllocationAligned.cpp @@ -191,9 +193,6 @@ SET(WTF_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}" ) -SET(WTF_LIBRARIES -) - IF (ENABLE_FAST_MALLOC) LIST(APPEND WTF_SOURCES TCSystemAlloc.cpp @@ -202,7 +201,7 @@ ELSE () ADD_DEFINITIONS(-DUSE_SYSTEM_MALLOC=1) ENDIF() -INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/wtf/Platform${PORT}.cmake) +WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() WEBKIT_WRAP_SOURCELIST(${WTF_SOURCES}) INCLUDE_DIRECTORIES(${WTF_INCLUDE_DIRECTORIES}) diff --git a/Source/JavaScriptCore/wtf/Compiler.h b/Source/JavaScriptCore/wtf/Compiler.h index 96ad6e40e..b8a019299 100644 --- a/Source/JavaScriptCore/wtf/Compiler.h +++ b/Source/JavaScriptCore/wtf/Compiler.h @@ -48,6 +48,9 @@ #define WTF_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS __has_feature(cxx_deleted_functions) #define WTF_COMPILER_SUPPORTS_CXX_NULLPTR __has_feature(cxx_nullptr) #define WTF_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks) +#define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_extension(c_static_assert) + +#define WTF_COMPILER_SUPPORTS_HAS_TRIVIAL_DESTRUCTOR __has_extension(has_trivial_destructor) #endif diff --git a/Source/JavaScriptCore/wtf/DataLog.cpp b/Source/JavaScriptCore/wtf/DataLog.cpp new file mode 100644 index 000000000..5a290e45a --- /dev/null +++ b/Source/JavaScriptCore/wtf/DataLog.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2012 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "config.h" +#include "DataLog.h" +#include <stdarg.h> +#include <wtf/Threading.h> + +#define DATA_LOG_TO_FILE 0 + +// Uncomment to force logging to the given file regardless of what the environment variable says. +// #define DATA_LOG_FILENAME "/tmp/WTFLog.txt" + +namespace WTF { + +#if DATA_LOG_TO_FILE +static FILE* file; + +static void initializeLogFileOnce() +{ +#ifdef DATA_LOG_FILENAME + const char* filename = DATA_LOG_FILENAME +#else + const char* filename = getenv("WTF_DATA_LOG_FILENAME"); +#endif + if (filename) { + file = fopen(filename, "w"); + if (!file) + fprintf(stderr, "Warning: Could not open log file %s for writing.\n", filename); + } + if (!file) + file = stderr; + + setvbuf(file, 0, _IONBF, 0); // Prefer unbuffered output, so that we get a full log upon crash or deadlock. +} + +#if OS(DARWIN) +static pthread_once_t initializeLogFileOnceKey = PTHREAD_ONCE_INIT; +#endif + +static void initializeLogFile() +{ +#if OS(DARWIN) + pthread_once(&initializeLogFileOnceKey, initializeLogFileOnce); +#else + if (!file) + initializeLogFileOnce(); +#endif +} + +FILE* dataFile() +{ + initializeLogFile(); + return file; +} +#else // DATA_LOG_TO_FILE +FILE* dataFile() +{ + return stderr; +} +#endif // DATA_LOG_TO_FILE + +void dataLogV(const char* format, va_list argList) +{ + vfprintf(dataFile(), format, argList); +} + +void dataLog(const char* format, ...) +{ + va_list argList; + va_start(argList, format); + dataLogV(format, argList); + va_end(argList); +} + +} // namespace WTF + diff --git a/Source/JavaScriptCore/wtf/DataLog.h b/Source/JavaScriptCore/wtf/DataLog.h new file mode 100644 index 000000000..bcbebb9e2 --- /dev/null +++ b/Source/JavaScriptCore/wtf/DataLog.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#ifndef DataLog_h +#define DataLog_h + +#include <stdarg.h> +#include <stdio.h> +#include <wtf/Platform.h> +#include <wtf/StdLibExtras.h> + +namespace WTF { + +FILE* dataFile(); + +void dataLogV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0); +void dataLog(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2); + +} // namespace WTF + +using WTF::dataLog; + +#endif // DataLog_h + diff --git a/Source/JavaScriptCore/wtf/DoublyLinkedList.h b/Source/JavaScriptCore/wtf/DoublyLinkedList.h index 361d71d7b..cd067ef0a 100644 --- a/Source/JavaScriptCore/wtf/DoublyLinkedList.h +++ b/Source/JavaScriptCore/wtf/DoublyLinkedList.h @@ -77,6 +77,8 @@ public: T* head() const; T* removeHead(); + T* tail() const; + void push(T*); void append(T*); void remove(T*); @@ -116,6 +118,11 @@ template<typename T> inline T* DoublyLinkedList<T>::head() const return m_head; } +template<typename T> inline T* DoublyLinkedList<T>::tail() const +{ + return m_tail; +} + template<typename T> inline void DoublyLinkedList<T>::push(T* node) { if (!m_head) { diff --git a/Source/JavaScriptCore/wtf/HashTable.cpp b/Source/JavaScriptCore/wtf/HashTable.cpp index 71d3f86ce..94bba9b32 100644 --- a/Source/JavaScriptCore/wtf/HashTable.cpp +++ b/Source/JavaScriptCore/wtf/HashTable.cpp @@ -44,15 +44,15 @@ HashTableStats::~HashTableStats() { // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown // if any thread was killed while holding the mutex. - printf("\nWTF::HashTable statistics\n\n"); - printf("%d accesses\n", numAccesses); - printf("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses); - printf("longest collision chain: %d\n", maxCollisions); + dataLog("\nWTF::HashTable statistics\n\n"); + dataLog("%d accesses\n", numAccesses); + dataLog("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses); + dataLog("longest collision chain: %d\n", maxCollisions); for (int i = 1; i <= maxCollisions; i++) { - printf(" %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses); + dataLog(" %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses); } - printf("%d rehashes\n", numRehashes); - printf("%d reinserts\n", numReinserts); + dataLog("%d rehashes\n", numRehashes); + dataLog("%d reinserts\n", numReinserts); } void HashTableStats::recordCollisionAtCount(int count) diff --git a/Source/JavaScriptCore/wtf/HashTraits.h b/Source/JavaScriptCore/wtf/HashTraits.h index 12e6b0699..e3783ed42 100644 --- a/Source/JavaScriptCore/wtf/HashTraits.h +++ b/Source/JavaScriptCore/wtf/HashTraits.h @@ -57,6 +57,7 @@ namespace WTF { template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> { typedef T TraitType; + typedef T EmptyValueType; static T emptyValue() { return T(); } @@ -112,7 +113,9 @@ namespace WTF { }; template<typename P> struct HashTraits<OwnPtr<P> > : SimpleClassHashTraits<OwnPtr<P> > { - static std::nullptr_t emptyValue() { return nullptr; } + typedef std::nullptr_t EmptyValueType; + + static EmptyValueType emptyValue() { return nullptr; } typedef PassOwnPtr<P> PassInType; static void store(PassOwnPtr<P> value, OwnPtr<P>& storage) { storage = value; } @@ -144,9 +147,10 @@ namespace WTF { typedef FirstTraitsArg FirstTraits; typedef SecondTraitsArg SecondTraits; typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType; + typedef pair<typename FirstTraits::EmptyValueType, typename SecondTraits::EmptyValueType> EmptyValueType; static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; - static TraitType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } + static EmptyValueType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; diff --git a/Source/JavaScriptCore/wtf/InlineASM.h b/Source/JavaScriptCore/wtf/InlineASM.h index 379ebd364..1c99e65a1 100644 --- a/Source/JavaScriptCore/wtf/InlineASM.h +++ b/Source/JavaScriptCore/wtf/InlineASM.h @@ -70,4 +70,11 @@ #define HIDE_SYMBOL(name) #endif +// FIXME: figure out how this works on all the platforms. I know that +// on Linux, the preferred form is ".Lstuff" as opposed to "Lstuff". +// Don't know about any of the others. +#if PLATFORM(MAC) +#define LOCAL_LABEL_STRING(name) "L" #name +#endif + #endif // InlineASM_h diff --git a/Source/JavaScriptCore/wtf/MainThread.cpp b/Source/JavaScriptCore/wtf/MainThread.cpp index 915126589..f8686aa31 100644 --- a/Source/JavaScriptCore/wtf/MainThread.cpp +++ b/Source/JavaScriptCore/wtf/MainThread.cpp @@ -34,6 +34,7 @@ #include "Functional.h" #include "StdLibExtras.h" #include "Threading.h" +#include <wtf/ThreadSpecific.h> #if PLATFORM(CHROMIUM) #error Chromium uses a different main thread implementation @@ -101,6 +102,7 @@ void initializeMainThread() mainThreadFunctionQueueMutex(); initializeMainThreadPlatform(); + initializeGCThreads(); } #else @@ -249,4 +251,42 @@ bool isMainThread() } #endif +#if ENABLE(PARALLEL_GC) +static ThreadSpecific<bool>* isGCThread; +#endif + +void initializeGCThreads() +{ +#if ENABLE(PARALLEL_GC) + isGCThread = new ThreadSpecific<bool>(); +#endif +} + +#if ENABLE(PARALLEL_GC) +void registerGCThread() +{ + if (!isGCThread) { + // This happens if we're running in a process that doesn't care about + // MainThread. + return; + } + + **isGCThread = true; +} + +bool isMainThreadOrGCThread() +{ + if (isGCThread->isSet() && **isGCThread) + return true; + + return isMainThread(); +} +#elif PLATFORM(MAC) +// This is necessary because JavaScriptCore.exp doesn't support preprocessor macros. +bool isMainThreadOrGCThread() +{ + return isMainThread(); +} +#endif + } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/MainThread.h b/Source/JavaScriptCore/wtf/MainThread.h index ff76a5fd3..4839c8117 100644 --- a/Source/JavaScriptCore/wtf/MainThread.h +++ b/Source/JavaScriptCore/wtf/MainThread.h @@ -52,11 +52,14 @@ WTF_EXPORT_PRIVATE void callOnMainThread(const Function<void ()>&); WTF_EXPORT_PRIVATE void setMainThreadCallbacksPaused(bool paused); WTF_EXPORT_PRIVATE bool isMainThread(); + +void initializeGCThreads(); + #if ENABLE(PARALLEL_GC) void registerGCThread(); WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread(); #elif PLATFORM(MAC) -bool isMainThreadOrGCThread(); +WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread(); #else inline bool isMainThreadOrGCThread() { return isMainThread(); } #endif diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.cpp b/Source/JavaScriptCore/wtf/MetaAllocator.cpp index d153faab7..ac6cba8d1 100644 --- a/Source/JavaScriptCore/wtf/MetaAllocator.cpp +++ b/Source/JavaScriptCore/wtf/MetaAllocator.cpp @@ -428,7 +428,7 @@ void MetaAllocator::freeFreeSpaceNode(FreeSpaceNode* node) #if ENABLE(META_ALLOCATOR_PROFILE) void MetaAllocator::dumpProfile() { - printf("num allocations = %u, num frees = %u\n", m_numAllocations, m_numFrees); + dataLog("num allocations = %u, num frees = %u\n", m_numAllocations, m_numFrees); } #endif diff --git a/Source/JavaScriptCore/wtf/NullPtr.cpp b/Source/JavaScriptCore/wtf/NullPtr.cpp index fb75cf6d5..d6b0429b1 100644 --- a/Source/JavaScriptCore/wtf/NullPtr.cpp +++ b/Source/JavaScriptCore/wtf/NullPtr.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "config.h" #include "NullPtr.h" -#if !COMPILER_SUPPORTS(CXX_NULLPTR) +#if !(COMPILER_SUPPORTS(CXX_NULLPTR) || defined(_LIBCPP_VERSION)) std::nullptr_t nullptr; diff --git a/Source/JavaScriptCore/wtf/NullPtr.h b/Source/JavaScriptCore/wtf/NullPtr.h index b65f8fab5..2d0919ca6 100644 --- a/Source/JavaScriptCore/wtf/NullPtr.h +++ b/Source/JavaScriptCore/wtf/NullPtr.h @@ -31,7 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // nullptr_t type and nullptr object. They are defined in the same namespaces they // would be in compiler and library that had the support. -#if COMPILER_SUPPORTS(CXX_NULLPTR) +#include <ciso646> + +#if COMPILER_SUPPORTS(CXX_NULLPTR) || defined(_LIBCPP_VERSION) #include <cstddef> diff --git a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp b/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp index 56c6089ff..5dbddc83e 100644 --- a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp +++ b/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp @@ -102,7 +102,7 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo result = mmap(result, bytes, protection, flags, fd, 0); if (result == MAP_FAILED) { - #if ENABLE(INTERPRETER) + #if ENABLE(CLASSIC_INTERPRETER) if (executable) result = 0; else diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp index fd5b1f847..2cc0bc643 100644 --- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp +++ b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp @@ -121,7 +121,7 @@ void ParallelEnvironment::ThreadPrivate::waitForFinish() m_threadCondition.wait(m_mutex); } -void* ParallelEnvironment::ThreadPrivate::workerThread(void* threadData) +void ParallelEnvironment::ThreadPrivate::workerThread(void* threadData) { ThreadPrivate* sharedThread = reinterpret_cast<ThreadPrivate*>(threadData); MutexLocker lock(sharedThread->m_mutex); @@ -136,7 +136,6 @@ void* ParallelEnvironment::ThreadPrivate::workerThread(void* threadData) sharedThread->m_threadCondition.wait(sharedThread->m_mutex); } - return 0; } } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h index 1c7d63c16..6de71067f 100644 --- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h +++ b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h @@ -69,7 +69,7 @@ public: return adoptRef(new ThreadPrivate()); } - static void* workerThread(void*); + static void workerThread(void*); private: ThreadIdentifier m_threadID; diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index e6d43dac3..76b11fe88 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -351,6 +351,11 @@ #define WTF_OS_FREEBSD 1 #endif +/* OS(HURD) - GNU/Hurd */ +#ifdef __GNU__ +#define WTF_OS_HURD 1 +#endif + /* OS(LINUX) - Linux */ #ifdef __linux__ #define WTF_OS_LINUX 1 @@ -394,6 +399,7 @@ || OS(ANDROID) \ || OS(DARWIN) \ || OS(FREEBSD) \ + || OS(HURD) \ || OS(LINUX) \ || OS(NETBSD) \ || OS(OPENBSD) \ @@ -459,7 +465,7 @@ #define WTF_USE_CA 1 #endif -/* USE(SKIA) for Win/Linux, CG for Mac, unless enabled */ +/* USE(SKIA) for Win/Linux/Mac/Android */ #if PLATFORM(CHROMIUM) #if OS(DARWIN) #if USE(SKIA_ON_MAC_CHROMIUM) @@ -470,6 +476,9 @@ #define WTF_USE_ATSUI 1 #define WTF_USE_CORE_TEXT 1 #define WTF_USE_ICCJPEG 1 +#elif OS(ANDROID) +#define WTF_USE_SKIA 1 +#define WTF_USE_GLES2_RENDERING 0 #else #define WTF_USE_SKIA 1 #define WTF_USE_CHROMIUM_NET 1 @@ -594,11 +603,11 @@ #define WTF_USE_PTHREADS 1 #if PLATFORM(IOS_SIMULATOR) - #define ENABLE_INTERPRETER 1 + #define ENABLE_CLASSIC_INTERPRETER 1 #define ENABLE_JIT 0 #define ENABLE_YARR_JIT 0 #else - #define ENABLE_INTERPRETER 1 + #define ENABLE_CLASSIC_INTERPRETER 1 #define ENABLE_JIT 1 #define ENABLE_YARR_JIT 1 #endif @@ -633,6 +642,7 @@ #define ENABLE_JIT 1 #endif #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 +#define ENABLE_LLINT 0 #if OS(DARWIN) #define WTF_USE_CF 1 #define WTF_USE_CORE_TEXT 1 @@ -919,6 +929,12 @@ #define ENABLE_JIT 1 #endif +/* On some of the platforms where we have a JIT, we want to also have the + low-level interpreter. */ +#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(ARM_THUMB2)) && USE(JSVALUE32_64) +#define ENABLE_LLINT 1 +#endif + #if !defined(ENABLE_DFG_JIT) && ENABLE(JIT) /* Enable the DFG JIT on X86 and X86_64. Only tested on Mac and GNU/Linux. */ #if (CPU(X86) || CPU(X86_64)) && (PLATFORM(MAC) || OS(LINUX)) @@ -953,10 +969,10 @@ #endif /* Ensure that either the JIT or the interpreter has been enabled. */ -#if !defined(ENABLE_INTERPRETER) && !ENABLE(JIT) -#define ENABLE_INTERPRETER 1 +#if !defined(ENABLE_CLASSIC_INTERPRETER) && !ENABLE(JIT) +#define ENABLE_CLASSIC_INTERPRETER 1 #endif -#if !(ENABLE(JIT) || ENABLE(INTERPRETER)) +#if !(ENABLE(JIT) || ENABLE(CLASSIC_INTERPRETER)) #error You have to have at least one execution model enabled to build JSC #endif @@ -989,8 +1005,8 @@ #if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) #define HAVE_COMPUTED_GOTO 1 #endif -#if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER) -#define ENABLE_COMPUTED_GOTO_INTERPRETER 1 +#if HAVE(COMPUTED_GOTO) && ENABLE(CLASSIC_INTERPRETER) +#define ENABLE_COMPUTED_GOTO_CLASSIC_INTERPRETER 1 #endif /* Regular Expression Tracing - Set to 1 to trace RegExp's in jsc. Results dumped at exit */ @@ -1123,7 +1139,7 @@ #define ENABLE_COMPARE_AND_SWAP 1 #endif -#if !defined(ENABLE_PARALLEL_GC) && (PLATFORM(MAC) || PLATFORM(IOS)) && ENABLE(COMPARE_AND_SWAP) +#if !defined(ENABLE_PARALLEL_GC) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT)) && ENABLE(COMPARE_AND_SWAP) #define ENABLE_PARALLEL_GC 1 #endif @@ -1141,7 +1157,7 @@ #define WTF_USE_COREMEDIA 1 #endif -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(QT) || PLATFORM(BLACKBERRY) #define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1 #endif @@ -1174,4 +1190,8 @@ #define ENABLE_TEXT_NOTIFICATIONS_ONLY 1 #endif +#if !defined(WTF_USE_WTFURL) +#define WTF_USE_WTFURL 0 +#endif + #endif /* WTF_Platform_h */ diff --git a/Source/JavaScriptCore/wtf/PlatformEfl.cmake b/Source/JavaScriptCore/wtf/PlatformEfl.cmake index 3887ead8c..1a13dbba3 100644 --- a/Source/JavaScriptCore/wtf/PlatformEfl.cmake +++ b/Source/JavaScriptCore/wtf/PlatformEfl.cmake @@ -1,6 +1,8 @@ LIST(APPEND WTF_SOURCES efl/MainThreadEfl.cpp efl/OwnPtrEfl.cpp + gobject/GOwnPtr.cpp + gobject/GRefPtr.cpp OSAllocatorPosix.cpp ThreadIdentifierDataPthreads.cpp @@ -9,24 +11,9 @@ LIST(APPEND WTF_SOURCES unicode/icu/CollatorICU.cpp ) -IF (ENABLE_GLIB_SUPPORT) - LIST(APPEND WTF_SOURCES - gobject/GOwnPtr.cpp - gobject/GRefPtr.cpp - ) - - LIST(APPEND WTF_INCLUDE_DIRECTORIES - ${Glib_INCLUDE_DIRS} - ${JAVASCRIPTCORE_DIR}/wtf/gobject - ) - - LIST(APPEND WTF_LIBRARIES - ${Glib_LIBRARIES} - ) -ENDIF () - LIST(APPEND WTF_LIBRARIES pthread + ${Glib_LIBRARIES} ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} ${ECORE_LIBRARIES} @@ -46,6 +33,8 @@ LIST(APPEND WTF_INCLUDE_DIRECTORIES ${ECORE_INCLUDE_DIRS} ${ECORE_EVAS_INCLUDE_DIRS} ${EVAS_INCLUDE_DIRS} + ${Glib_INCLUDE_DIRS} ${ICU_INCLUDE_DIRS} + ${JAVASCRIPTCORE_DIR}/wtf/gobject ${JAVASCRIPTCORE_DIR}/wtf/unicode/ ) diff --git a/Source/JavaScriptCore/wtf/SentinelLinkedList.h b/Source/JavaScriptCore/wtf/SentinelLinkedList.h index ecd602452..3943aa5de 100644 --- a/Source/JavaScriptCore/wtf/SentinelLinkedList.h +++ b/Source/JavaScriptCore/wtf/SentinelLinkedList.h @@ -86,6 +86,8 @@ public: iterator begin(); iterator end(); + + bool isEmpty() { return begin() == end(); } private: RawNode m_headSentinel; diff --git a/Source/JavaScriptCore/wtf/StdLibExtras.h b/Source/JavaScriptCore/wtf/StdLibExtras.h index e4d7c8fc0..2a0a9f950 100644 --- a/Source/JavaScriptCore/wtf/StdLibExtras.h +++ b/Source/JavaScriptCore/wtf/StdLibExtras.h @@ -114,6 +114,11 @@ inline bool isPointerAligned(void* p) return !((intptr_t)(p) & (sizeof(char*) - 1)); } +inline bool is8ByteAligned(void* p) +{ + return !((uintptr_t)(p) & (sizeof(double) - 1)); +} + /* * C++'s idea of a reinterpret_cast lacks sufficient cojones. */ @@ -292,6 +297,7 @@ inline void* operator new(size_t, NotNullTag, void* location) using WTF::KB; using WTF::isPointerAligned; +using WTF::is8ByteAligned; using WTF::binarySearch; using WTF::bitwise_cast; using WTF::safeCast; diff --git a/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h b/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h index f1e147268..2d8599eb9 100644 --- a/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h +++ b/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h @@ -31,7 +31,7 @@ namespace WTF { -typedef void* (*ThreadFunction)(void* argument); +typedef void (*ThreadFunction)(void* argument); struct ThreadFunctionInvocation { ThreadFunctionInvocation(ThreadFunction function, void* data) diff --git a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp b/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp index b3b690f70..0badf939a 100644 --- a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp +++ b/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp @@ -36,8 +36,8 @@ #include "Threading.h" -#if OS(ANDROID) -// PTHREAD_KEYS_MAX is not defined in bionic, so explicitly define it here. +#if OS(ANDROID) || OS(HURD) +// PTHREAD_KEYS_MAX is not defined in bionic nor in Hurd, so explicitly define it here. #define PTHREAD_KEYS_MAX 1024 #else #include <limits.h> diff --git a/Source/JavaScriptCore/wtf/ThreadSpecific.h b/Source/JavaScriptCore/wtf/ThreadSpecific.h index 242acc0d3..f20a3f3df 100644 --- a/Source/JavaScriptCore/wtf/ThreadSpecific.h +++ b/Source/JavaScriptCore/wtf/ThreadSpecific.h @@ -77,12 +77,11 @@ private: // have exited). It's unlikely that any user of this call will be in that situation - and having // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly. ~ThreadSpecific(); - + T* get(); void set(T*); void static destroy(void* ptr); -#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS) struct Data { WTF_MAKE_NONCOPYABLE(Data); public: @@ -94,7 +93,6 @@ private: void (*destructor)(void*); #endif }; -#endif #if USE(PTHREADS) pthread_key_t m_key; @@ -239,6 +237,6 @@ inline T& ThreadSpecific<T>::operator*() return *operator T*(); } -} +} // namespace WTF -#endif +#endif // WTF_ThreadSpecific_h diff --git a/Source/JavaScriptCore/wtf/Threading.cpp b/Source/JavaScriptCore/wtf/Threading.cpp index d8dbbae4f..8d658e934 100644 --- a/Source/JavaScriptCore/wtf/Threading.cpp +++ b/Source/JavaScriptCore/wtf/Threading.cpp @@ -25,6 +25,8 @@ #include "config.h" #include "Threading.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <string.h> @@ -47,7 +49,7 @@ public: Mutex creationMutex; }; -static void* threadEntryPoint(void* contextData) +static void threadEntryPoint(void* contextData) { NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); @@ -64,7 +66,7 @@ static void* threadEntryPoint(void* contextData) void* data = context->data; delete context; - return entryPoint(data); + entryPoint(data); } ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) @@ -86,14 +88,58 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* #if PLATFORM(MAC) || PLATFORM(WIN) +// For ABI compatibility with Safari on Mac / Windows: Safari uses the private +// createThread() and waitForThreadCompletion() functions directly and we need +// to keep the old ABI compatibility until it's been rebuilt. + +typedef void* (*ThreadFunctionWithReturnValue)(void* argument); + +WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name); + +struct ThreadFunctionWithReturnValueInvocation { + ThreadFunctionWithReturnValueInvocation(ThreadFunctionWithReturnValue function, void* data) + : function(function) + , data(data) + { + } + + ThreadFunctionWithReturnValue function; + void* data; +}; + +static void compatEntryPoint(void* param) +{ + // Balanced by .leakPtr() in createThread. + OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(static_cast<ThreadFunctionWithReturnValueInvocation*>(param)); + invocation->function(invocation->data); +} + +ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name) +{ + OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(new ThreadFunctionWithReturnValueInvocation(entryPoint, data)); + + // Balanced by adoptPtr() in compatEntryPoint. + return createThread(compatEntryPoint, invocation.leakPtr(), name); +} + +WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**); + +int waitForThreadCompletion(ThreadIdentifier threadID, void**) +{ + return waitForThreadCompletion(threadID); +} + // This function is deprecated but needs to be kept around for backward // compatibility. Use the 3-argument version of createThread above. -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunction entryPoint, void* data); +WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data); -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) +ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data) { - return createThread(entryPoint, data, 0); + OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(new ThreadFunctionWithReturnValueInvocation(entryPoint, data)); + + // Balanced by adoptPtr() in compatEntryPoint. + return createThread(compatEntryPoint, invocation.leakPtr(), 0); } #endif diff --git a/Source/JavaScriptCore/wtf/Threading.h b/Source/JavaScriptCore/wtf/Threading.h index 1dee5da1c..b5d432681 100644 --- a/Source/JavaScriptCore/wtf/Threading.h +++ b/Source/JavaScriptCore/wtf/Threading.h @@ -78,7 +78,7 @@ namespace WTF { typedef uint32_t ThreadIdentifier; -typedef void* (*ThreadFunction)(void* argument); +typedef void (*ThreadFunction)(void* argument); // This function must be called from the main thread. It is safe to call it repeatedly. // Darwin is an exception to this rule: it is OK to call it from any thread, the only @@ -97,7 +97,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN void initializeCurrentThreadInternal(const char* threadName); WTF_EXPORT_PRIVATE ThreadIdentifier currentThread(); -WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**); +WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier); WTF_EXPORT_PRIVATE void detachThread(ThreadIdentifier); WTF_EXPORT_PRIVATE void yield(); diff --git a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp b/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp index 763ec2bbb..abd350dbb 100644 --- a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -40,9 +40,12 @@ #include "HashMap.h" #include "RandomNumberSeed.h" #include "StdLibExtras.h" +#include "ThreadFunctionInvocation.h" #include "ThreadIdentifierDataPthreads.h" #include "ThreadSpecific.h" #include "UnusedParam.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <wtf/WTFThreadData.h> #include <errno.h> @@ -152,6 +155,15 @@ void clearPthreadHandleForIdentifier(ThreadIdentifier id) threadMap().remove(id); } +static void* wtfThreadEntryPoint(void* param) +{ + // Balanced by .leakPtr() in createThreadInternal. + OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param)); + invocation->function(invocation->data); + + return 0; +} + #if PLATFORM(BLACKBERRY) ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName) { @@ -171,8 +183,9 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con LOG_ERROR("pthread_attr_getstack() failed: %d", errno); } + OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data)); pthread_t threadHandle; - if (pthread_create(&threadHandle, &attr, entryPoint, data)) { + if (pthread_create(&threadHandle, &attr, wtfThreadEntryPoint, invocation.get())) { LOG_ERROR("pthread_create() failed: %d", errno); threadHandle = 0; } @@ -183,17 +196,26 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con if (!threadHandle) return 0; + // Balanced by adoptPtr() in wtfThreadEntryPoint. + ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr(); + UNUSED_PARAM(leakedInvocation); + return establishIdentifierForPthreadHandle(threadHandle); } #else ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) { + OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data)); pthread_t threadHandle; - if (pthread_create(&threadHandle, 0, entryPoint, data)) { - LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data); + if (pthread_create(&threadHandle, 0, wtfThreadEntryPoint, invocation.get())) { + LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get()); return 0; } + // Balanced by adoptPtr() in wtfThreadEntryPoint. + ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr(); + UNUSED_PARAM(leakedInvocation); + return establishIdentifierForPthreadHandle(threadHandle); } #endif @@ -217,7 +239,7 @@ void initializeCurrentThreadInternal(const char* threadName) ThreadIdentifierData::initialize(id); } -int waitForThreadCompletion(ThreadIdentifier threadID, void** result) +int waitForThreadCompletion(ThreadIdentifier threadID) { ASSERT(threadID); @@ -225,7 +247,7 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) if (!pthreadHandle) return 0; - int joinResult = pthread_join(pthreadHandle, result); + int joinResult = pthread_join(pthreadHandle, 0); if (joinResult == EDEADLK) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); diff --git a/Source/JavaScriptCore/wtf/ThreadingWin.cpp b/Source/JavaScriptCore/wtf/ThreadingWin.cpp index ac0f73f19..bc32262ce 100644 --- a/Source/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/Source/JavaScriptCore/wtf/ThreadingWin.cpp @@ -210,14 +210,14 @@ static void clearThreadHandleForIdentifier(ThreadIdentifier id) static unsigned __stdcall wtfThreadEntryPoint(void* param) { OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param)); - void* result = invocation->function(invocation->data); + invocation->function(invocation->data); #if !USE(PTHREADS) && OS(WINDOWS) // Do the TLS cleanup. ThreadSpecificThreadExit(); #endif - return reinterpret_cast<unsigned>(result); + return 0; } ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName) @@ -252,7 +252,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con return threadID; } -int waitForThreadCompletion(ThreadIdentifier threadID, void** result) +int waitForThreadCompletion(ThreadIdentifier threadID) { ASSERT(threadID); diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h index 175f1a582..29bbd37d9 100644 --- a/Source/JavaScriptCore/wtf/Vector.h +++ b/Source/JavaScriptCore/wtf/Vector.h @@ -181,7 +181,10 @@ namespace WTF { static void uninitializedFill(T* dst, T* dstEnd, const T& val) { ASSERT(sizeof(T) == sizeof(char)); - memset(dst, val, dstEnd - dst); +#if COMPILER(GCC) && defined(_FORTIFY_SOURCE) + if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst))) +#endif + memset(dst, val, dstEnd - dst); } }; diff --git a/Source/JavaScriptCore/wtf/dtoa.cpp b/Source/JavaScriptCore/wtf/dtoa.cpp index 3732fe614..4c4041e1c 100644 --- a/Source/JavaScriptCore/wtf/dtoa.cpp +++ b/Source/JavaScriptCore/wtf/dtoa.cpp @@ -228,25 +228,6 @@ static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */ b.append((uint32_t)carry); } -static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9) -{ - b.sign = 0; - b.resize(1); - b.words()[0] = y9; - - int i = 9; - if (9 < nd0) { - s += 9; - do { - multadd(b, 10, *s++ - '0'); - } while (++i < nd0); - s++; - } else - s += 10; - for (; i < nd; i++) - multadd(b, 10, *s++ - '0'); -} - static int hi0bits(uint32_t x) { int k = 0; @@ -603,57 +584,6 @@ static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef c.resize(wa); } -static double ulp(U *x) -{ - register int32_t L; - U u; - - L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1; - word0(&u) = L; - word1(&u) = 0; - return dval(&u); -} - -static double b2d(const BigInt& a, int* e) -{ - const uint32_t* xa; - const uint32_t* xa0; - uint32_t w; - uint32_t y; - uint32_t z; - int k; - U d; - -#define d0 word0(&d) -#define d1 word1(&d) - - xa0 = a.words(); - xa = xa0 + a.size(); - y = *--xa; - ASSERT(y); - k = hi0bits(y); - *e = 32 - k; - if (k < Ebits) { - d0 = Exp_1 | (y >> (Ebits - k)); - w = xa > xa0 ? *--xa : 0; - d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k)); - goto returnD; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | (y << k) | (z >> (32 - k)); - y = xa > xa0 ? *--xa : 0; - d1 = (z << k) | (y >> (32 - k)); - } else { - d0 = Exp_1 | y; - d1 = z; - } -returnD: -#undef d0 -#undef d1 - return dval(&d); -} - static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) { int de, k; @@ -701,23 +631,6 @@ static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) #undef d0 #undef d1 -static double ratio(const BigInt& a, const BigInt& b) -{ - U da, db; - int k, ka, kb; - - dval(&da) = b2d(a, &ka); - dval(&db) = b2d(b, &kb); - k = ka - kb + 32 * (a.size() - b.size()); - if (k > 0) - word0(&da) += k * Exp_msk1; - else { - k = -k; - word0(&db) += k * Exp_msk1; - } - return dval(&da) / dval(&db); -} - static const double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, @@ -735,443 +648,26 @@ static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, #define Scale_Bit 0x10 #define n_bigtens 5 +template<AllowTrailingJunkTag allowTrailingJunk> double strtod(const char* s00, char** se) { - int scale; - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - const char *s, *s0, *s1; - double aadj, aadj1; - U aadj2, adj, rv, rv0; - int32_t L; - uint32_t y, z; - BigInt bb, bb1, bd, bd0, bs, delta; - - sign = nz0 = nz = 0; - dval(&rv) = 0; - for (s = s00; ; s++) { - switch (*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } - } -break2: - if (*s == '0') { - nz0 = 1; - while (*++s == '0') { } - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = (10 * y) + c - '0'; - else if (nd < 16) - z = (10 * z) + c - '0'; - nd0 = nd; - if (c == '.') { - c = *++s; - if (!nd) { - for (; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto haveDig; - } - goto digDone; - } - for (; c >= '0' && c <= '9'; c = *++s) { -haveDig: - nz++; - if (c -= '0') { - nf += nz; - for (i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = (10 * y) + c; - else if (nd <= DBL_DIG + 1) - z = (10 * z) + c; - nz = 0; - } - } - } -digDone: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) - goto ret0; - s00 = s; - esign = 0; - switch (c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while (c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while ((c = *++s) >= '0' && c <= '9') - L = (10 * L) + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } else - e = 0; - } else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -ret0: - s = s00; - sign = 0; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(&rv) = y; - if (k > 9) - dval(&rv) = tens[k - 9] * dval(&rv) + z; - if (nd <= DBL_DIG) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ - e -= i; - dval(&rv) *= tens[i]; - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; - } - } else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); - goto ret; - } - } - e1 += nd - k; - - scale = 0; - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ((i = e1 & 15)) - dval(&rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { -ovfl: -#if HAVE(ERRNO_H) - errno = ERANGE; -#endif - /* Can't trust HUGE_VAL */ - word0(&rv) = Exp_mask; - word1(&rv) = 0; - goto ret; - } - e1 >>= 4; - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(&rv) -= P * Exp_msk1; - dval(&rv) *= bigtens[j]; - if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) - goto ovfl; - if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(&rv) = Big0; - word1(&rv) = Big1; - } else - word0(&rv) += P * Exp_msk1; - } - } else if (e1 < 0) { - e1 = -e1; - if ((i = e1 & 15)) - dval(&rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; - if (e1 & Scale_Bit) - scale = 2 * P; - for (j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { - /* scaled rv is denormal; clear j low bits */ - if (j >= 32) { - word1(&rv) = 0; - if (j >= 53) - word0(&rv) = (P + 2) * Exp_msk1; - else - word0(&rv) &= 0xffffffff << (j - 32); - } else - word1(&rv) &= 0xffffffff << j; - } - if (!dval(&rv)) { -undfl: - dval(&rv) = 0.; -#if HAVE(ERRNO_H) - errno = ERANGE; -#endif - goto ret; - } - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - s2b(bd0, s0, nd0, nd, y); - - for (;;) { - bd = bd0; - d2b(bb, &rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ - i2b(bs, 1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; - j = bbe - scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; - bb2 += j; - bd2 += j; - bd2 += scale; - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - pow5mult(bs, bb5); - mult(bb, bs); - } - if (bb2 > 0) - lshift(bb, bb2); - if (bd5 > 0) - pow5mult(bd, bd5); - if (bd2 > 0) - lshift(bd, bd2); - if (bs2 > 0) - lshift(bs, bs2); - diff(delta, bb, bd); - dsign = delta.sign; - delta.sign = 0; - i = cmp(delta, bs); - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask - || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1 - ) { - break; - } - if (!delta.words()[0] && delta.size() <= 1) { - /* exact result */ - break; - } - lshift(delta, Log2P); - if (cmp(delta, bs) > 0) - goto dropDown; - break; - } - if (!i) { - /* exactly half-way between */ - if (dsign) { - if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 - && word1(&rv) == ( - (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) - ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) : - 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1; - word1(&rv) = 0; - dsign = 0; - break; - } - } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { -dropDown: - /* boundary case -- decrement exponent */ - if (scale) { - L = word0(&rv) & Exp_mask; - if (L <= (2 * P + 1) * Exp_msk1) { - if (L > (P + 2) * Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - goto undfl; - } - } - L = (word0(&rv) & Exp_mask) - Exp_msk1; - word0(&rv) = L | Bndry_mask1; - word1(&rv) = 0xffffffff; - break; - } - if (!(word1(&rv) & LSB)) - break; - if (dsign) - dval(&rv) += ulp(&rv); - else { - dval(&rv) -= ulp(&rv); - if (!dval(&rv)) - goto undfl; - } - dsign = 1 - dsign; - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = aadj1 = 1.; - else if (word1(&rv) || word0(&rv) & Bndry_mask) { - if (word1(&rv) == Tiny1 && !word0(&rv)) - goto undfl; - aadj = 1.; - aadj1 = -1.; - } else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2. / FLT_RADIX) - aadj = 1. / FLT_RADIX; - else - aadj *= 0.5; - aadj1 = -aadj; - } - } else { - aadj *= 0.5; - aadj1 = dsign ? aadj : -aadj; - } - y = word0(&rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) { - dval(&rv0) = dval(&rv); - word0(&rv) -= P * Exp_msk1; - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) - goto ovfl; - word0(&rv) = Big0; - word1(&rv) = Big1; - goto cont; - } - word0(&rv) += P * Exp_msk1; - } else { - if (scale && y <= 2 * P * Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (uint32_t)aadj) <= 0) - z = 1; - aadj = z; - aadj1 = dsign ? aadj : -aadj; - } - dval(&aadj2) = aadj1; - word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y; - aadj1 = dval(&aadj2); - } - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - } - z = word0(&rv) & Exp_mask; - if (!scale && y == z) { - /* Can we stop now? */ - L = (int32_t)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } else if (aadj < .4999999 / FLT_RADIX) - break; - } -cont: - {} - } - if (scale) { - word0(&rv0) = Exp_1 - 2 * P * Exp_msk1; - word1(&rv0) = 0; - dval(&rv) *= dval(&rv0); -#if HAVE(ERRNO_H) - /* try to avoid the bug of testing an 8087 register value */ - if (!word0(&rv) && !word1(&rv)) - errno = ERANGE; -#endif - } -ret: + int length = strlen(s00); + double_conversion::StringToDoubleConverter converter( + (allowTrailingJunk ? double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK : 0) | + double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES, + 0.0, + (allowTrailingJunk ? std::numeric_limits<double>::quiet_NaN() : 0.0), + "Infinity", "NaN"); + int processedCharacterCount = 0; + double result = converter.StringToDouble(s00, length, &processedCharacterCount); if (se) - *se = const_cast<char*>(s); - return sign ? -dval(&rv) : dval(&rv); + *se = const_cast<char*>(s00 + processedCharacterCount); + return result; } +template double strtod<AllowTrailingJunk>(const char*, char**); +template double strtod<DisallowTrailingJunk>(const char*, char**); + static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) { size_t n; diff --git a/Source/JavaScriptCore/wtf/dtoa.h b/Source/JavaScriptCore/wtf/dtoa.h index d27c59206..a4672c07a 100644 --- a/Source/JavaScriptCore/wtf/dtoa.h +++ b/Source/JavaScriptCore/wtf/dtoa.h @@ -35,9 +35,12 @@ WTF_EXPORT_PRIVATE void dtoa(DtoaBuffer result, double dd, bool& sign, int& expo WTF_EXPORT_PRIVATE void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); WTF_EXPORT_PRIVATE void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); +enum AllowTrailingJunkTag { DisallowTrailingJunk = 0, AllowTrailingJunk }; + // s00: input string. Must not be 0 and must be terminated by 0. // se: *se will have the last consumed character position + 1. -WTF_EXPORT_PRIVATE double strtod(const char* s00, char** se); +template<AllowTrailingJunkTag allowTrailingJunk> +double strtod(const char* s00, char** se); // Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits. const unsigned NumberToStringBufferLength = 96; diff --git a/Source/JavaScriptCore/wtf/dtoa/utils.h b/Source/JavaScriptCore/wtf/dtoa/utils.h index d5cfe9c29..64e5ad42f 100644 --- a/Source/JavaScriptCore/wtf/dtoa/utils.h +++ b/Source/JavaScriptCore/wtf/dtoa/utils.h @@ -49,7 +49,7 @@ defined(__ARMEL__) || \ defined(_MIPS_ARCH_MIPS32R2) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#elif CPU(MIPS) || CPU(PPC) || CPU(PPC64) || OS(WINCE) || CPU(SH4) || CPU(S390) || CPU(S390X) +#elif CPU(MIPS) || CPU(PPC) || CPU(PPC64) || OS(WINCE) || CPU(SH4) || CPU(S390) || CPU(S390X) || CPU(IA64) || CPU(SPARC) || CPU(ALPHA) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #elif defined(_M_IX86) || defined(__i386__) #if defined(_WIN32) diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp index c727956ce..dfe187d78 100644 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp +++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp @@ -37,6 +37,11 @@ template <> void freeOwnedGPtr<GList>(GList* ptr) g_list_free(ptr); } +template <> void freeOwnedGPtr<GSList>(GSList* ptr) +{ + g_slist_free(ptr); +} + template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr) { if (ptr) diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h index 221971f97..4b2dcb77b 100644 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h +++ b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h @@ -35,6 +35,7 @@ namespace WTF { template <typename T> inline void freeOwnedGPtr(T* ptr); template<> void freeOwnedGPtr<GError>(GError*); template<> void freeOwnedGPtr<GList>(GList*); +template<> void freeOwnedGPtr<GSList>(GSList*); template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); template<> void freeOwnedGPtr<GDir>(GDir*); template<> void freeOwnedGPtr<GTimer>(GTimer*); diff --git a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h index e2b2ba6b8..cb3842b78 100644 --- a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h +++ b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h @@ -53,6 +53,7 @@ typedef struct _GInputStream GInputStream; typedef struct _GList GList; typedef struct _GPatternSpec GPatternSpec; typedef struct _GPollableOutputStream GPollableOutputStream; +typedef struct _GSList GSList; typedef struct _GSocketClient GSocketClient; typedef struct _GSocketConnection GSocketConnection; typedef struct _GSource GSource; diff --git a/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm b/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm index fbc625032..5a82f40a6 100644 --- a/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm +++ b/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm @@ -35,7 +35,6 @@ #import <wtf/Assertions.h> #import <wtf/HashSet.h> #import <wtf/Threading.h> -#import <wtf/ThreadSpecific.h> @interface JSWTFMainThreadCaller : NSObject { } @@ -59,17 +58,6 @@ static bool mainThreadEstablishedAsPthreadMain; static pthread_t mainThreadPthread; static NSThread* mainThreadNSThread; -#if ENABLE(PARALLEL_GC) -static ThreadSpecific<bool>* isGCThread; - -static void initializeGCThreads() -{ - isGCThread = new ThreadSpecific<bool>(); -} -#else -static void initializeGCThreads() { } -#endif - void initializeMainThreadPlatform() { ASSERT(!staticMainThreadCaller); @@ -145,31 +133,4 @@ bool isMainThread() return pthread_equal(pthread_self(), mainThreadPthread); } -#if ENABLE(PARALLEL_GC) -void registerGCThread() -{ - if (!isGCThread) { - // This happens if we're running in a process that doesn't care about - // MainThread. - return; - } - - **isGCThread = true; -} - -bool isMainThreadOrGCThread() -{ - if (isGCThread->isSet() && **isGCThread) - return true; - - return isMainThread(); -} -#else -// This is necessary because JavaScriptCore.exp doesn't support preprocessor macros. -bool isMainThreadOrGCThread() -{ - return isMainThread(); -} -#endif - } // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.h b/Source/JavaScriptCore/wtf/text/StringImpl.h index 3862effb6..667335b86 100644 --- a/Source/JavaScriptCore/wtf/text/StringImpl.h +++ b/Source/JavaScriptCore/wtf/text/StringImpl.h @@ -43,6 +43,8 @@ typedef const struct __CFString * CFStringRef; // Landing the file moves in one patch, will follow on with patches to change the namespaces. namespace JSC { struct IdentifierCStringTranslator; +namespace LLInt { class Data; } +class LLIntOffsetsExtractor; template <typename T> struct IdentifierCharBufferTranslator; struct IdentifierLCharFromUCharTranslator; } @@ -72,7 +74,9 @@ class StringImpl { friend struct WTF::SubstringTranslator; friend struct WTF::UCharBufferTranslator; friend class AtomicStringImpl; - + friend class JSC::LLInt::Data; + friend class JSC::LLIntOffsetsExtractor; + private: enum BufferOwnership { BufferInternal, @@ -735,7 +739,7 @@ bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b) return !a.size(); if (a.size() != b->length()) return false; - return !memcmp(a.data(), b->characters(), b->length()); + return !memcmp(a.data(), b->characters(), b->length() * sizeof(UChar)); } WTF_EXPORT_PRIVATE int codePointCompare(const StringImpl*, const StringImpl*); diff --git a/Source/JavaScriptCore/wtf/text/WTFString.cpp b/Source/JavaScriptCore/wtf/text/WTFString.cpp index df74c65af..04c970a7c 100644 --- a/Source/JavaScriptCore/wtf/text/WTFString.cpp +++ b/Source/JavaScriptCore/wtf/text/WTFString.cpp @@ -24,6 +24,8 @@ #include <stdarg.h> #include <wtf/ASCIICType.h> +#include <wtf/DataLog.h> +#include <wtf/MathExtras.h> #include <wtf/text/CString.h> #include <wtf/StringExtras.h> #include <wtf/Vector.h> @@ -1034,7 +1036,7 @@ intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) return toIntegralType<intptr_t, UChar>(data, lengthOfCharactersAsInteger<UChar>(data, length), ok, 10); } -template <typename CharType> +template <typename CharType, WTF::AllowTrailingJunkTag allowTrailingJunk> static inline double toDoubleType(const CharType* data, size_t length, bool* ok, bool* didReadNumber) { if (!length) { @@ -1051,9 +1053,9 @@ static inline double toDoubleType(const CharType* data, size_t length, bool* ok, bytes[length] = '\0'; char* start = bytes.data(); char* end; - double val = WTF::strtod(start, &end); + double val = WTF::strtod<allowTrailingJunk>(start, &end); if (ok) - *ok = (end == 0 || *end == '\0'); + *ok = (end == 0 || *end == '\0') && !isnan(val); if (didReadNumber) *didReadNumber = end - start; return val; @@ -1061,24 +1063,36 @@ static inline double toDoubleType(const CharType* data, size_t length, bool* ok, double charactersToDouble(const LChar* data, size_t length, bool* ok, bool* didReadNumber) { - return toDoubleType<LChar>(data, length, ok, didReadNumber); + return toDoubleType<LChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber); } double charactersToDouble(const UChar* data, size_t length, bool* ok, bool* didReadNumber) { - return toDoubleType<UChar>(data, length, ok, didReadNumber); + return toDoubleType<UChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber); } float charactersToFloat(const LChar* data, size_t length, bool* ok, bool* didReadNumber) { // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<LChar>(data, length, ok, didReadNumber)); + return static_cast<float>(toDoubleType<LChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber)); } float charactersToFloat(const UChar* data, size_t length, bool* ok, bool* didReadNumber) { // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<UChar>(data, length, ok, didReadNumber)); + return static_cast<float>(toDoubleType<UChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber)); +} + +float charactersToFloatIgnoringJunk(const LChar* data, size_t length, bool* ok, bool* didReadNumber) +{ + // FIXME: This will return ok even when the string fits into a double but not a float. + return static_cast<float>(toDoubleType<LChar, WTF::AllowTrailingJunk>(data, length, ok, didReadNumber)); +} + +float charactersToFloatIgnoringJunk(const UChar* data, size_t length, bool* ok, bool* didReadNumber) +{ + // FIXME: This will return ok even when the string fits into a double but not a float. + return static_cast<float>(toDoubleType<UChar, WTF::AllowTrailingJunk>(data, length, ok, didReadNumber)); } const String& emptyString() @@ -1097,7 +1111,7 @@ Vector<char> asciiDebug(String& string); void String::show() const { - fprintf(stderr, "%s\n", asciiDebug(impl()).data()); + dataLog("%s\n", asciiDebug(impl()).data()); } String* string(const char* s) diff --git a/Source/JavaScriptCore/wtf/text/WTFString.h b/Source/JavaScriptCore/wtf/text/WTFString.h index 2d32e6916..edc842154 100644 --- a/Source/JavaScriptCore/wtf/text/WTFString.h +++ b/Source/JavaScriptCore/wtf/text/WTFString.h @@ -87,7 +87,9 @@ intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trai WTF_EXPORT_PRIVATE double charactersToDouble(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); WTF_EXPORT_PRIVATE double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); float charactersToFloat(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +WTF_EXPORT_PRIVATE float charactersToFloatIgnoringJunk(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); WTF_EXPORT_PRIVATE float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +WTF_EXPORT_PRIVATE float charactersToFloatIgnoringJunk(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); enum FloatConversionFlags { ShouldRoundSignificantFigures = 1 << 0, diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp b/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp new file mode 100644 index 000000000..3c1519136 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2010 Google, 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 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 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 "config.h" +#include "ParsedURL.h" + +#if USE(WTFURL) + +#include "URLComponent.h" +#include "URLParser.h" + +namespace WTF { + +ParsedURL::ParsedURL(const URLString& spec) + : m_spec(spec) +{ + // FIXME: Handle non-standard URLs. + if (spec.string().isEmpty()) + return; + URLParser<UChar>::parseStandardURL(spec.string().characters(), spec.string().length(), m_segments); +} + +String ParsedURL::scheme() const +{ + return segment(m_segments.scheme); +} + +String ParsedURL::username() const +{ + return segment(m_segments.username); +} + +String ParsedURL::password() const +{ + return segment(m_segments.password); +} + +String ParsedURL::host() const +{ + return segment(m_segments.host); +} + +String ParsedURL::port() const +{ + return segment(m_segments.port); +} + +String ParsedURL::path() const +{ + return segment(m_segments.path); +} + +String ParsedURL::query() const +{ + return segment(m_segments.query); +} + +String ParsedURL::fragment() const +{ + return segment(m_segments.fragment); +} + +String ParsedURL::segment(const URLComponent& component) const +{ + if (!component.isValid()) + return String(); + return m_spec.string().substring(component.begin(), component.length()); +} + +} + +#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.h b/Source/JavaScriptCore/wtf/url/api/ParsedURL.h new file mode 100644 index 000000000..023589564 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/api/ParsedURL.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Google, 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 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 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. + */ + +#ifndef ParsedURL_h +#define ParsedURL_h + +#if USE(WTFURL) + +#include "URLSegments.h" +#include "URLString.h" + +namespace WTF { + +class URLComponent; + +class ParsedURL { +public: + explicit ParsedURL(const URLString&); + + // FIXME: Add a method for parsing non-canonicalized URLs. + + String scheme() const; + String username() const; + String password() const; + String host() const; + String port() const; + String path() const; + String query() const; + String fragment() const; + + URLString spec() { return m_spec; } + +private: + inline String segment(const URLComponent&) const; + + URLString m_spec; + URLSegments m_segments; +}; + +} + +#endif // USE(WTFURL) + +#endif diff --git a/Source/JavaScriptCore/wtf/url/api/URLString.h b/Source/JavaScriptCore/wtf/url/api/URLString.h new file mode 100644 index 000000000..329f51e2f --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/api/URLString.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Google, 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 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 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. + */ + +#ifndef URLString_h +#define URLString_h + +#if USE(WTFURL) + +#include "WTFString.h" + +namespace WTF { + +// URLString represents a string that's a canonicalized URL. +class URLString { +public: + URLString() { } + + const String& string() const { return m_string;} + +private: + friend class ParsedURL; + + // URLString can only be constructed by a ParsedURL. + explicit URLString(const String& string) + : m_string(string) + { + } + + String m_string; +}; + +} + +#endif // USE(WTFURL) + +#endif + diff --git a/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h b/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h new file mode 100644 index 000000000..59a7f18af --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h @@ -0,0 +1,74 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + +#ifndef RawURLBuffer_h +#define RawURLBuffer_h + +#if USE(WTFURL) + +#include "URLBuffer.h" + +namespace WTF { + +// Simple implementation of the URLBuffer using new[]. This class +// also supports a static buffer so if it is allocated on the stack, most +// URLs can be canonicalized with no heap allocations. +template<typename CharacterType, int inlineCapacity = 1024> +class RawURLBuffer : public URLBuffer<CharacterType> { +public: + RawURLBuffer() : URLBuffer<CharacterType>() + { + this->m_buffer = m_inlineBuffer; + this->m_capacity = inlineCapacity; + } + + virtual ~RawURLBuffer() + { + if (this->m_buffer != m_inlineBuffer) + delete[] this->m_buffer; + } + + virtual void resize(int size) + { + CharacterType* newBuffer = new CharacterType[size]; + memcpy(newBuffer, this->m_buffer, sizeof(CharacterType) * (this->m_length < size ? this->m_length : size)); + if (this->m_buffer != m_inlineBuffer) + delete[] this->m_buffer; + this->m_buffer = newBuffer; + this->m_capacity = size; + } + +protected: + CharacterType m_inlineBuffer[inlineCapacity]; +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // RawURLBuffer_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLBuffer.h b/Source/JavaScriptCore/wtf/url/src/URLBuffer.h new file mode 100644 index 000000000..84a4f85c2 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLBuffer.h @@ -0,0 +1,140 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + +#ifndef URLBuffer_h +#define URLBuffer_h + +#if USE(WTFURL) + +namespace WTF { + +// Base class for the canonicalizer output, this maintains a buffer and +// supports simple resizing and append operations on it. +// +// It is VERY IMPORTANT that no virtual function calls be made on the common +// code path. We only have two virtual function calls, the destructor and a +// resize function that is called when the existing buffer is not big enough. +// The derived class is then in charge of setting up our buffer which we will +// manage. +template<typename CharacterType> +class URLBuffer { +public: + URLBuffer() : m_buffer(0), m_capacity(0), m_length(0) { } + virtual ~URLBuffer() { } + + // Implemented to resize the buffer. This function should update the buffer + // pointer to point to the new buffer, and any old data up to |m_length| in + // the buffer must be copied over. + // + // The new size must be larger than m_capacity. + virtual void resize(int) = 0; + + inline char at(int offset) const { return m_buffer[offset]; } + inline void set(int offset, CharacterType ch) + { + // FIXME: Add ASSERT(offset < length()); + m_buffer[offset] = ch; + } + + // Returns the current capacity of the buffer. The length() is the number of + // characters that have been declared to be written, but the capacity() is + // the number that can be written without reallocation. If the caller must + // write many characters at once, it can make sure there is enough capacity, + // write the data, then use setLength() to declare the new length(). + int capacity() const { return m_capacity; } + int length() const { return m_length; } + + // The output will NOT be 0-terminated. Call length() to get the length. + const CharacterType* data() const { return m_buffer; } + CharacterType* data() { return m_buffer; } + + // Shortens the URL to the new length. Used for "backing up" when processing + // relative paths. This can also be used if an external function writes a lot + // of data to the buffer (when using the "Raw" version below) beyond the end, + // to declare the new length. + void setLength(int length) + { + // FIXME: Add ASSERT(length < capacity()); + m_length = length; + } + + // This is the most performance critical function, since it is called for + // every character. + void append(CharacterType ch) + { + // In VC2005, putting this common case first speeds up execution + // dramatically because this branch is predicted as taken. + if (m_length < m_capacity) { + m_buffer[m_length] = ch; + ++m_length; + return; + } + + if (!grow(1)) + return; + + m_buffer[m_length] = ch; + ++m_length; + } + + void append(const CharacterType* str, int strLength) + { + if (m_length + strLength > m_capacity) { + if (!grow(m_length + strLength - m_capacity)) + return; + } + for (int i = 0; i < strLength; i++) + m_buffer[m_length + i] = str[i]; + m_length += strLength; + } + +protected: + // Returns true if the buffer could be resized, false on OOM. + bool grow(int minimumAdditionalCapacity) + { + static const int minimumCapacity = 16; + int newCapacity = m_capacity ? m_capacity : minimumCapacity; + do { + if (newCapacity >= (1 << 30)) // Prevent overflow below. + return false; + newCapacity *= 2; + } while (newCapacity < m_capacity + minimumAdditionalCapacity); + resize(newCapacity); + return true; + } + + CharacterType* m_buffer; + int m_capacity; + int m_length; // Used characters in the buffer. +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLBuffer_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp new file mode 100644 index 000000000..f56e7207c --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp @@ -0,0 +1,177 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 "config.h" +#include "URLCharacterTypes.h" + +#if USE(WTFURL) + +namespace WTF { + +const unsigned char URLCharacterTypes::characterTypeTable[0x100] = { + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x00 - 0x0f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x10 - 0x1f + InvalidCharacter, // 0x20 ' ' (escape spaces in queries) + QueryCharacter | UserInfoCharacter, // 0x21 ! + InvalidCharacter, // 0x22 " + InvalidCharacter, // 0x23 # (invalid in query since it marks the ref) + QueryCharacter | UserInfoCharacter, // 0x24 $ + QueryCharacter | UserInfoCharacter, // 0x25 % + QueryCharacter | UserInfoCharacter, // 0x26 & + QueryCharacter | UserInfoCharacter, // 0x27 ' + QueryCharacter | UserInfoCharacter, // 0x28 ( + QueryCharacter | UserInfoCharacter, // 0x29 ) + QueryCharacter | UserInfoCharacter, // 0x2a * + QueryCharacter | UserInfoCharacter, // 0x2b + + QueryCharacter | UserInfoCharacter, // 0x2c , + QueryCharacter | UserInfoCharacter, // 0x2d - + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x2e . + QueryCharacter, // 0x2f / + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x30 0 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x31 1 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x32 2 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x33 3 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x34 4 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x35 5 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x36 6 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x37 7 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x38 8 + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x39 9 + QueryCharacter, // 0x3a : + QueryCharacter, // 0x3b ; + InvalidCharacter, // 0x3c < + QueryCharacter, // 0x3d = + InvalidCharacter, // 0x3e > + QueryCharacter, // 0x3f ? + QueryCharacter, // 0x40 @ + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x41 A + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x42 B + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x43 C + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x44 D + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x45 E + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x46 F + QueryCharacter | UserInfoCharacter, // 0x47 G + QueryCharacter | UserInfoCharacter, // 0x48 H + QueryCharacter | UserInfoCharacter, // 0x49 I + QueryCharacter | UserInfoCharacter, // 0x4a J + QueryCharacter | UserInfoCharacter, // 0x4b K + QueryCharacter | UserInfoCharacter, // 0x4c L + QueryCharacter | UserInfoCharacter, // 0x4d M + QueryCharacter | UserInfoCharacter, // 0x4e N + QueryCharacter | UserInfoCharacter, // 0x4f O + QueryCharacter | UserInfoCharacter, // 0x50 P + QueryCharacter | UserInfoCharacter, // 0x51 Q + QueryCharacter | UserInfoCharacter, // 0x52 R + QueryCharacter | UserInfoCharacter, // 0x53 S + QueryCharacter | UserInfoCharacter, // 0x54 T + QueryCharacter | UserInfoCharacter, // 0x55 U + QueryCharacter | UserInfoCharacter, // 0x56 V + QueryCharacter | UserInfoCharacter, // 0x57 W + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x58 X + QueryCharacter | UserInfoCharacter, // 0x59 Y + QueryCharacter | UserInfoCharacter, // 0x5a Z + QueryCharacter, // 0x5b [ + QueryCharacter, // 0x5c '\' + QueryCharacter, // 0x5d ] + QueryCharacter, // 0x5e ^ + QueryCharacter | UserInfoCharacter, // 0x5f _ + QueryCharacter, // 0x60 ` + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x61 a + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x62 b + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x63 c + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x64 d + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x65 e + QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x66 f + QueryCharacter | UserInfoCharacter, // 0x67 g + QueryCharacter | UserInfoCharacter, // 0x68 h + QueryCharacter | UserInfoCharacter, // 0x69 i + QueryCharacter | UserInfoCharacter, // 0x6a j + QueryCharacter | UserInfoCharacter, // 0x6b k + QueryCharacter | UserInfoCharacter, // 0x6c l + QueryCharacter | UserInfoCharacter, // 0x6d m + QueryCharacter | UserInfoCharacter, // 0x6e n + QueryCharacter | UserInfoCharacter, // 0x6f o + QueryCharacter | UserInfoCharacter, // 0x70 p + QueryCharacter | UserInfoCharacter, // 0x71 q + QueryCharacter | UserInfoCharacter, // 0x72 r + QueryCharacter | UserInfoCharacter, // 0x73 s + QueryCharacter | UserInfoCharacter, // 0x74 t + QueryCharacter | UserInfoCharacter, // 0x75 u + QueryCharacter | UserInfoCharacter, // 0x76 v + QueryCharacter | UserInfoCharacter, // 0x77 w + QueryCharacter | UserInfoCharacter | IPv4Character, // 0x78 x + QueryCharacter | UserInfoCharacter, // 0x79 y + QueryCharacter | UserInfoCharacter, // 0x7a z + QueryCharacter, // 0x7b { + QueryCharacter, // 0x7c | + QueryCharacter, // 0x7d } + QueryCharacter | UserInfoCharacter, // 0x7e ~ + InvalidCharacter, // 0x7f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x80 - 0x8f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x90 - 0x9f + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xa0 - 0xaf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xb0 - 0xbf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xc0 - 0xcf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xd0 - 0xdf + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xe0 - 0xef + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, + InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xf0 - 0xff +}; + +} + +#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h new file mode 100644 index 000000000..6edb98ca2 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h @@ -0,0 +1,65 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + +#ifndef URLCharacterTypes_h +#define URLCharacterTypes_h + +#if USE(WTFURL) + +namespace WTF { + +class URLCharacterTypes { +public: + static inline bool isQueryChar(unsigned char c) { return isCharOfType(c, QueryCharacter); } + static inline bool isIPv4Char(unsigned char c) { return isCharOfType(c, IPv4Character); } + static inline bool isHexChar(unsigned char c) { return isCharOfType(c, HexCharacter); } + +private: + enum CharTypes { + InvalidCharacter = 0, + QueryCharacter = 1 << 0, + UserInfoCharacter = 1 << 1, + IPv4Character = 1 << 2, + HexCharacter = 1 << 3, + DecimalCharacter = 1 << 4, + OctalCharacter = 1 << 5, + }; + + static const unsigned char characterTypeTable[0x100]; + + static inline bool isCharOfType(unsigned char c, CharTypes type) + { + return !!(characterTypeTable[c] & type); + } +}; + +} + +#endif // USE(WTFURL) + +#endif // URLCharacterTypes_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLComponent.h b/Source/JavaScriptCore/wtf/url/src/URLComponent.h new file mode 100644 index 000000000..747a80b80 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLComponent.h @@ -0,0 +1,81 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + +#ifndef URLComponent_h +#define URLComponent_h + +#if USE(WTFURL) + +namespace WTF { + +// Represents a substring for URL parsing. +class URLComponent { +public: + URLComponent() : m_begin(0), m_length(-1) { } + URLComponent(int begin, int length) : m_begin(begin), m_length(length) { } + + // Helper that returns a component created with the given begin and ending + // points. The ending point is non-inclusive. + static inline URLComponent fromRange(int begin, int end) + { + return URLComponent(begin, end - begin); + } + + // Returns true if this component is valid, meaning the length is given. Even + // valid components may be empty to record the fact that they exist. + bool isValid() const { return m_length != -1; } + + bool isNonEmpty() const { return m_length > 0; } + bool isEmptyOrInvalid() const { return m_length <= 0; } + + void reset() + { + m_begin = 0; + m_length = -1; + } + + bool operator==(const URLComponent& other) const { return m_begin == other.m_begin && m_length == other.m_length; } + + int begin() const { return m_begin; } + void setBegin(int begin) { m_begin = begin; } + + int length() const { return m_length; } + void setLength(int length) { m_length = length; } + + int end() const { return m_begin + m_length; } + +private: + int m_begin; // Byte offset in the string of this component. + int m_length; // Will be -1 if the component is unspecified. +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLComponent_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp b/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp new file mode 100644 index 000000000..5acdcde24 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp @@ -0,0 +1,43 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 "config.h" +#include "URLEscape.h" + +#if USE(WTFURL) + +namespace WTF { + +const char hexCharacterTable[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', +}; + +} + +#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLEscape.h b/Source/JavaScriptCore/wtf/url/src/URLEscape.h new file mode 100644 index 000000000..e010012a3 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLEscape.h @@ -0,0 +1,53 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + + +#ifndef URLEscape_h +#define URLEscape_h + +#if USE(WTFURL) + +#include "URLBuffer.h" + +namespace WTF { + +extern const char hexCharacterTable[16]; + +template<typename InChar, typename OutChar> +inline void appendURLEscapedCharacter(InChar ch, URLBuffer<OutChar>& buffer) +{ + buffer.append('%'); + buffer.append(hexCharacterTable[ch >> 4]); + buffer.append(hexCharacterTable[ch & 0xf]); +} + +} + +#endif // USE(WTFURL) + +#endif diff --git a/Source/JavaScriptCore/wtf/url/src/URLParser.h b/Source/JavaScriptCore/wtf/url/src/URLParser.h new file mode 100644 index 000000000..01f738cf3 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLParser.h @@ -0,0 +1,579 @@ +/* Based on nsURLParsers.cc from Mozilla + * ------------------------------------- + * Copyright (C) 1998 Netscape Communications Corporation. + * + * Other contributors: + * Darin Fisher (original author) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#ifndef URLParser_h +#define URLParser_h + +#include "URLComponent.h" +#include "URLSegments.h" + +#if USE(WTFURL) + +namespace WTF { + +template<typename CharacterType> +class URLParser { +public: + enum SpecialPort { + UnspecifiedPort = -1, + InvalidPort = -2, + }; + + // This handles everything that may be an authority terminator, including + // backslash. For special backslash handling see parseAfterScheme. + static bool isPossibleAuthorityTerminator(CharacterType ch) + { + return isURLSlash(ch) || ch == '?' || ch == '#' || ch == ';'; + } + + // Given an already-identified auth section, breaks it into its constituent + // parts. The port number will be parsed and the resulting integer will be + // filled into the given *port variable, or -1 if there is no port number + // or it is invalid. + static void parseAuthority(const CharacterType* spec, const URLComponent& auth, URLComponent& username, URLComponent& password, URLComponent& host, URLComponent& port) + { + // FIXME: add ASSERT(auth.isValid()); // We should always get an authority. + if (!auth.length()) { + username.reset(); + password.reset(); + host.reset(); + port.reset(); + return; + } + + // Search backwards for @, which is the separator between the user info + // and the server info. RFC 3986 forbids @ from occuring in auth, but + // someone might include it in a password unescaped. + int i = auth.begin() + auth.length() - 1; + while (i > auth.begin() && spec[i] != '@') + --i; + + if (spec[i] == '@') { + // Found user info: <user-info>@<server-info> + parseUserInfo(spec, URLComponent(auth.begin(), i - auth.begin()), username, password); + parseServerInfo(spec, URLComponent::fromRange(i + 1, auth.begin() + auth.length()), host, port); + } else { + // No user info, everything is server info. + username.reset(); + password.reset(); + parseServerInfo(spec, auth, host, port); + } + } + + static bool extractScheme(const CharacterType* spec, int specLength, URLComponent& scheme) + { + // Skip leading whitespace and control characters. + int begin = 0; + while (begin < specLength && shouldTrimFromURL(spec[begin])) + begin++; + if (begin == specLength) + return false; // Input is empty or all whitespace. + + // Find the first colon character. + for (int i = begin; i < specLength; i++) { + if (spec[i] == ':') { + scheme = URLComponent::fromRange(begin, i); + return true; + } + } + return false; // No colon found: no scheme + } + + // Fills in all members of the URLSegments structure (except for the + // scheme) for standard URLs. + // + // |spec| is the full spec being parsed, of length |specLength|. + // |afterScheme| is the character immediately following the scheme (after + // the colon) where we'll begin parsing. + static void parseAfterScheme(const CharacterType* spec, int specLength, int afterScheme, URLSegments& parsed) + { + int numberOfSlashes = consecutiveSlashes(spec, afterScheme, specLength); + int afterSlashes = afterScheme + numberOfSlashes; + + // First split into two main parts, the authority (username, password, + // host, and port) and the full path (path, query, and reference). + URLComponent authority; + URLComponent fullPath; + + // Found "//<some data>", looks like an authority section. Treat + // everything from there to the next slash (or end of spec) to be the + // authority. Note that we ignore the number of slashes and treat it as + // the authority. + int authEnd = nextAuthorityTerminator(spec, afterSlashes, specLength); + authority = URLComponent(afterSlashes, authEnd - afterSlashes); + + if (authEnd == specLength) // No beginning of path found. + fullPath = URLComponent(); + else // Everything starting from the slash to the end is the path. + fullPath = URLComponent(authEnd, specLength - authEnd); + + // Now parse those two sub-parts. + parseAuthority(spec, authority, parsed.username, parsed.password, parsed.host, parsed.port); + parsePath(spec, fullPath, parsed.path, parsed.query, parsed.fragment); + } + + // The main parsing function for standard URLs. Standard URLs have a scheme, + // host, path, etc. + static void parseStandardURL(const CharacterType* spec, int specLength, URLSegments& parsed) + { + // FIXME: add ASSERT(specLength >= 0); + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + int afterScheme; + if (extractScheme(spec, specLength, parsed.scheme)) + afterScheme = parsed.scheme.end() + 1; // Skip past the colon. + else { + // Say there's no scheme when there is a colon. We could also say + // that everything is the scheme. Both would produce an invalid + // URL, but this way seems less wrong in more cases. + parsed.scheme.reset(); + afterScheme = begin; + } + parseAfterScheme(spec, specLength, afterScheme, parsed); + } + + static void parsePath(const CharacterType* spec, const URLComponent& path, URLComponent& filepath, URLComponent& query, URLComponent& fragment) + { + // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<fragment> + + // Special case when there is no path. + if (!path.isValid()) { + filepath.reset(); + query.reset(); + fragment.reset(); + return; + } + // FIXME: add ASSERT(path.length() > 0); // We should never have 0 length paths. + + // Search for first occurrence of either ? or #. + int pathEnd = path.begin() + path.length(); + + int querySeparator = -1; // Index of the '?' + int refSeparator = -1; // Index of the '#' + for (int i = path.begin(); i < pathEnd; i++) { + switch (spec[i]) { + case '?': + if (querySeparator < 0) + querySeparator = i; + break; + case '#': + refSeparator = i; + i = pathEnd; // Break out of the loop. + break; + default: + break; + } + } + + // Markers pointing to the character after each of these corresponding + // components. The code below works from the end back to the beginning, + // and will update these indices as it finds components that exist. + int fileEnd, queryEnd; + + // Fragment: from the # to the end of the path. + if (refSeparator >= 0) { + fileEnd = refSeparator; + queryEnd = refSeparator; + fragment = URLComponent::fromRange(refSeparator + 1, pathEnd); + } else { + fileEnd = pathEnd; + queryEnd = pathEnd; + fragment.reset(); + } + + // Query fragment: everything from the ? to the next boundary (either + // the end of the path or the fragment fragment). + if (querySeparator >= 0) { + fileEnd = querySeparator; + query = URLComponent::fromRange(querySeparator + 1, queryEnd); + } else + query.reset(); + + // File path: treat an empty file path as no file path. + if (fileEnd != path.begin()) + filepath = URLComponent::fromRange(path.begin(), fileEnd); + else + filepath.reset(); + } + + // Initializes a path URL which is merely a scheme followed by a path. + // Examples include "about:foo" and "javascript:alert('bar');" + static void parsePathURL(const CharacterType* spec, int specLength, URLSegments& parsed) + { + // Get the non-path and non-scheme parts of the URL out of the way, we + // never use them. + parsed.username.reset(); + parsed.password.reset(); + parsed.host.reset(); + parsed.port.reset(); + parsed.query.reset(); + parsed.fragment.reset(); + + // Strip leading & trailing spaces and control characters. + // FIXME: Perhaps this is unnecessary? + int begin = 0; + trimURL(spec, begin, specLength); + + // Handle empty specs or ones that contain only whitespace or control + // chars. + if (begin == specLength) { + parsed.scheme.reset(); + parsed.path.reset(); + return; + } + + // Extract the scheme, with the path being everything following. We also + // handle the case where there is no scheme. + if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { + // Offset the results since we gave extractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + + // For compatibility with the standard URL parser, we treat no path + // as -1, rather than having a length of 0 (we normally wouldn't + // care so much for these non-standard URLs). + if (parsed.scheme.end() == specLength - 1) + parsed.path.reset(); + else + parsed.path = URLComponent::fromRange(parsed.scheme.end() + 1, specLength); + } else { + // No scheme found, just path. + parsed.scheme.reset(); + parsed.path = URLComponent::fromRange(begin, specLength); + } + } + + static void parseMailtoURL(const CharacterType* spec, int specLength, URLSegments& parsed) + { + // FIXME: add ASSERT(specLength >= 0); + + // Get the non-path and non-scheme parts of the URL out of the way, we + // never use them. + parsed.username.reset(); + parsed.password.reset(); + parsed.host.reset(); + parsed.port.reset(); + parsed.fragment.reset(); + parsed.query.reset(); // May use this; reset for convenience. + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + // Handle empty specs or ones that contain only whitespace or control + // chars. + if (begin == specLength) { + parsed.scheme.reset(); + parsed.path.reset(); + return; + } + + int pathBegin = -1; + int pathEnd = -1; + + // Extract the scheme, with the path being everything following. We also + // handle the case where there is no scheme. + if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { + // Offset the results since we gave extractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + + if (parsed.scheme.end() != specLength - 1) { + pathBegin = parsed.scheme.end() + 1; + pathEnd = specLength; + } + } else { + // No scheme found, just path. + parsed.scheme.reset(); + pathBegin = begin; + pathEnd = specLength; + } + + // Split [pathBegin, pathEnd) into a path + query. + for (int i = pathBegin; i < pathEnd; ++i) { + if (spec[i] == '?') { + parsed.query = URLComponent::fromRange(i + 1, pathEnd); + pathEnd = i; + break; + } + } + + // For compatibility with the standard URL parser, treat no path as + // -1, rather than having a length of 0 + if (pathBegin == pathEnd) + parsed.path.reset(); + else + parsed.path = URLComponent::fromRange(pathBegin, pathEnd); + } + + static int parsePort(const CharacterType* spec, const URLComponent& component) + { + // Easy success case when there is no port. + const int maxDigits = 5; + if (component.isEmptyOrInvalid()) + return UnspecifiedPort; + + URLComponent nonZeroDigits(component.end(), 0); + for (int i = 0; i < component.length(); ++i) { + if (spec[component.begin() + i] != '0') { + nonZeroDigits = URLComponent::fromRange(component.begin() + i, component.end()); + break; + } + } + if (!nonZeroDigits.length()) + return 0; // All digits were 0. + + if (nonZeroDigits.length() > maxDigits) + return InvalidPort; + + int port = 0; + for (int i = 0; i < nonZeroDigits.length(); ++i) { + CharacterType ch = spec[nonZeroDigits.begin() + i]; + if (!isPortDigit(ch)) + return InvalidPort; + port *= 10; + port += static_cast<char>(ch) - '0'; + } + if (port > 65535) + return InvalidPort; + return port; + } + + static void extractFileName(const CharacterType* spec, const URLComponent& path, URLComponent& fileName) + { + // Handle empty paths: they have no file names. + if (path.isEmptyOrInvalid()) { + fileName.reset(); + return; + } + + // Search backwards for a parameter, which is a normally unused field + // in a URL delimited by a semicolon. We parse the parameter as part of + // the path, but here, we don't want to count it. The last semicolon is + // the parameter. + int fileEnd = path.end(); + for (int i = path.end() - 1; i > path.begin(); --i) { + if (spec[i] == ';') { + fileEnd = i; + break; + } + } + + // Now search backwards from the filename end to the previous slash + // to find the beginning of the filename. + for (int i = fileEnd - 1; i >= path.begin(); --i) { + if (isURLSlash(spec[i])) { + // File name is everything following this character to the end + fileName = URLComponent::fromRange(i + 1, fileEnd); + return; + } + } + + // No slash found, this means the input was degenerate (generally paths + // will start with a slash). Let's call everything the file name. + fileName = URLComponent::fromRange(path.begin(), fileEnd); + } + + static bool extractQueryKeyValue(const CharacterType* spec, URLComponent& query, URLComponent& key, URLComponent& value) + { + if (query.isEmptyOrInvalid()) + return false; + + int start = query.begin(); + int current = start; + int end = query.end(); + + // We assume the beginning of the input is the beginning of the "key" + // and we skip to the end of it. + key.setBegin(current); + while (current < end && spec[current] != '&' && spec[current] != '=') + ++current; + key.setLength(current - key.begin()); + + // Skip the separator after the key (if any). + if (current < end && spec[current] == '=') + ++current; + + // Find the value part. + value.setBegin(current); + while (current < end && spec[current] != '&') + ++current; + value.setLength(current - value.begin()); + + // Finally skip the next separator if any + if (current < end && spec[current] == '&') + ++current; + + // Save the new query + query = URLComponent::fromRange(current, end); + return true; + } + +// FIXME: This should be protected or private. +public: + // We treat slashes and backslashes the same for IE compatibility. + static inline bool isURLSlash(CharacterType ch) + { + return ch == '/' || ch == '\\'; + } + + // Returns true if we should trim this character from the URL because it is + // a space or a control character. + static inline bool shouldTrimFromURL(CharacterType ch) + { + return ch <= ' '; + } + + // Given an already-initialized begin index and end index (the index after + // the last CharacterType in spec), this shrinks the range to eliminate + // "should-be-trimmed" characters. + static inline void trimURL(const CharacterType* spec, int& begin, int& end) + { + // Strip leading whitespace and control characters. + while (begin < end && shouldTrimFromURL(spec[begin])) + ++begin; + + // Strip trailing whitespace and control characters. We need the >i + // test for when the input string is all blanks; we don't want to back + // past the input. + while (end > begin && shouldTrimFromURL(spec[end - 1])) + --end; + } + + // Counts the number of consecutive slashes starting at the given offset + // in the given string of the given length. + static inline int consecutiveSlashes(const CharacterType *string, int beginOffset, int stringLength) + { + int count = 0; + while (beginOffset + count < stringLength && isURLSlash(string[beginOffset + count])) + ++count; + return count; + } + +private: + // URLParser cannot be constructed. + URLParser(); + + // Returns true if the given character is a valid digit to use in a port. + static inline bool isPortDigit(CharacterType ch) + { + return ch >= '0' && ch <= '9'; + } + + // Returns the offset of the next authority terminator in the input starting + // from startOffset. If no terminator is found, the return value will be equal + // to specLength. + static int nextAuthorityTerminator(const CharacterType* spec, int startOffset, int specLength) + { + for (int i = startOffset; i < specLength; i++) { + if (isPossibleAuthorityTerminator(spec[i])) + return i; + } + return specLength; // Not found. + } + + static void parseUserInfo(const CharacterType* spec, const URLComponent& user, URLComponent& username, URLComponent& password) + { + // Find the first colon in the user section, which separates the + // username and password. + int colonOffset = 0; + while (colonOffset < user.length() && spec[user.begin() + colonOffset] != ':') + ++colonOffset; + + if (colonOffset < user.length()) { + // Found separator: <username>:<password> + username = URLComponent(user.begin(), colonOffset); + password = URLComponent::fromRange(user.begin() + colonOffset + 1, user.begin() + user.length()); + } else { + // No separator, treat everything as the username + username = user; + password = URLComponent(); + } + } + + static void parseServerInfo(const CharacterType* spec, const URLComponent& serverInfo, URLComponent& host, URLComponent& port) + { + if (!serverInfo.length()) { + // No server info, host name is empty. + host.reset(); + port.reset(); + return; + } + + // If the host starts with a left-bracket, assume the entire host is an + // IPv6 literal. Otherwise, assume none of the host is an IPv6 literal. + // This assumption will be overridden if we find a right-bracket. + // + // Our IPv6 address canonicalization code requires both brackets to + // exist, but the ability to locate an incomplete address can still be + // useful. + int ipv6Terminator = spec[serverInfo.begin()] == '[' ? serverInfo.end() : -1; + int colon = -1; + + // Find the last right-bracket, and the last colon. + for (int i = serverInfo.begin(); i < serverInfo.end(); i++) { + switch (spec[i]) { + case ']': + ipv6Terminator = i; + break; + case ':': + colon = i; + break; + default: + break; + } + } + + if (colon > ipv6Terminator) { + // Found a port number: <hostname>:<port> + host = URLComponent::fromRange(serverInfo.begin(), colon); + if (!host.length()) + host.reset(); + port = URLComponent::fromRange(colon + 1, serverInfo.end()); + } else { + // No port: <hostname> + host = serverInfo; + port.reset(); + } + } +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLParser_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h b/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h new file mode 100644 index 000000000..467c497fd --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h @@ -0,0 +1,109 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + + +#ifndef URLQueryCanonicalizer_h +#define URLQueryCanonicalizer_h + +#if USE(WTFURL) + +#include "RawURLBuffer.h" +#include "URLBuffer.h" +#include "URLCharacterTypes.h" +#include "URLComponent.h" +#include "URLEscape.h" + +namespace WTF { + +template<typename InChar, typename OutChar, void convertCharset(const InChar*, int length, URLBuffer<char>&)> +class URLQueryCanonicalizer { +public: + static void canonicalize(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer, URLComponent& resultQuery) + { + if (query.length() < 0) { + resultQuery = URLComponent(); + return; + } + + buffer->append('?'); + resultQuery.setBegin(buffer->length()); + convertToQueryEncoding(spec, query, buffer); + resultQuery.setLength(buffer->length() - resultQuery.begin()); + } + +private: + static bool isAllASCII(const InChar* spec, const URLComponent& query) + { + int end = query.end(); + for (int i = query.begin(); i < end; ++i) { + if (static_cast<unsigned>(spec[i]) >= 0x80) + return false; + } + return true; + } + +#ifndef NDEBUG + static bool isRaw8Bit(const InChar* source, int length) + { + for (int i = source; i < length; ++i) { + if (source[i] & 0xFF != source[i]) + return false; + } + return true; + } +#endif + + static void appendRaw8BitQueryString(const InChar* source, int length, URLBuffer<OutChar>* buffer) + { + ASSERT(isRaw8Bit(source, length)); + for (int i = 0; i < length; ++i) { + if (!URLCharacterTypes::isQueryChar(source[i])) + appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), buffer); + else + buffer->append(static_cast<char>(source[i])); + } + } + + static void convertToQueryEncoding(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer) + { + if (isAllASCII(spec, query)) { + appendRaw8BitQueryString(&spec[query.begin()], query.length(), buffer); + return; + } + + RawURLBuffer<char, 1024> convertedQuery; + convertCharset(spec, query, convertedQuery); + appendRaw8BitQueryString(convertedQuery.data(), convertedQuery.length(), buffer); + } +}; + +} + +#endif // USE(WTFURL) + +#endif diff --git a/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp b/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp new file mode 100644 index 000000000..182b0d45b --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp @@ -0,0 +1,114 @@ +/* Based on nsURLParsers.cc from Mozilla + * ------------------------------------- + * Copyright (C) 1998 Netscape Communications Corporation. + * + * Other contributors: + * Darin Fisher (original author) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#include "config.h" +#include "URLSegments.h" + +#if USE(WTFURL) + +namespace WTF { + +int URLSegments::length() const +{ + if (fragment.isValid()) + return fragment.end(); + return charactersBefore(Fragment, false); +} + +int URLSegments::charactersBefore(ComponentType type, bool includeDelimiter) const +{ + if (type == Scheme) + return scheme.begin(); + + int current = 0; + if (scheme.isValid()) + current = scheme.end() + 1; // Advance over the ':' at the end of the scheme. + + if (username.isValid()) { + if (type <= Username) + return username.begin(); + current = username.end() + 1; // Advance over the '@' or ':' at the end. + } + + if (password.isValid()) { + if (type <= Password) + return password.begin(); + current = password.end() + 1; // Advance over the '@' at the end. + } + + if (host.isValid()) { + if (type <= Host) + return host.begin(); + current = host.end(); + } + + if (port.isValid()) { + if (type < Port || (type == Port && includeDelimiter)) + return port.begin() - 1; // Back over delimiter. + if (type == Port) + return port.begin(); // Don't want delimiter counted. + current = port.end(); + } + + if (path.isValid()) { + if (type <= Path) + return path.begin(); + current = path.end(); + } + + if (query.isValid()) { + if (type < Query || (type == Query && includeDelimiter)) + return query.begin() - 1; // Back over delimiter. + if (type == Query) + return query.begin(); // Don't want delimiter counted. + current = query.end(); + } + + if (fragment.isValid()) { + if (type == Fragment && !includeDelimiter) + return fragment.begin(); // Back over delimiter. + + // When there is a fragment and we get here, the component we wanted was before + // this and not found, so we always know the beginning of the fragment is right. + return fragment.begin() - 1; // Don't want delimiter counted. + } + + return current; +} + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLSegments.h b/Source/JavaScriptCore/wtf/url/src/URLSegments.h new file mode 100644 index 000000000..64d0619b8 --- /dev/null +++ b/Source/JavaScriptCore/wtf/url/src/URLSegments.h @@ -0,0 +1,109 @@ +// Copyright 2007, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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. + +#ifndef URLSegments_h +#define URLSegments_h + +#include "URLComponent.h" + +#if USE(WTFURL) + +namespace WTF { + +// A structure that holds the identified parts of an input URL. This structure +// does NOT store the URL itself. The caller will have to store the URL text +// and its corresponding Parsed structure separately. +class URLSegments { +public: + // Identifies different components. + enum ComponentType { + Scheme, + Username, + Password, + Host, + Port, + Path, + Query, + Fragment, + }; + + URLSegments() { } + + // Returns the length of the URL (the end of the last component). + // + // Note that for some invalid, non-canonical URLs, this may not be the length + // of the string. For example "http://": the parsed structure will only + // contain an entry for the four-character scheme, and it doesn't know about + // the "://". For all other last-components, it will return the real length. + int length() const; + + // Returns the number of characters before the given component if it exists, + // or where the component would be if it did exist. This will return the + // string length if the component would be appended to the end. + // + // Note that this can get a little funny for the port, query, and fragment + // components which have a delimiter that is not counted as part of the + // component. The |includeDelimiter| flag controls if you want this counted + // as part of the component or not when the component exists. + // + // This example shows the difference between the two flags for two of these + // delimited components that is present (the port and query) and one that + // isn't (the reference). The components that this flag affects are marked + // with a *. + // 0 1 2 + // 012345678901234567890 + // Example input: http://foo:80/?query + // include_delim=true, ...=false ("<-" indicates different) + // Scheme: 0 0 + // Username: 5 5 + // Password: 5 5 + // Host: 7 7 + // *Port: 10 11 <- + // Path: 13 13 + // *Query: 14 15 <- + // *Fragment: 20 20 + // + int charactersBefore(ComponentType, bool includeDelimiter) const; + + // Each component excludes the related delimiters and has a length of -1 + // if that component is absent but 0 if the component exists but is empty. + URLComponent scheme; + URLComponent username; + URLComponent password; + URLComponent host; + URLComponent port; + URLComponent path; + URLComponent query; + URLComponent fragment; +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLSegments_h |