diff options
| author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
| commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
| tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WTF/wtf | |
| parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
| download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz | |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WTF/wtf')
246 files changed, 5544 insertions, 13689 deletions
diff --git a/Source/WTF/wtf/AVLTree.h b/Source/WTF/wtf/AVLTree.h index f2f82e170..61f627e8b 100644 --- a/Source/WTF/wtf/AVLTree.h +++ b/Source/WTF/wtf/AVLTree.h @@ -66,7 +66,7 @@ namespace WTF { template<unsigned maxDepth> class AVLTreeDefaultBSet { public: - bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; } + bool& operator[](unsigned i) { ASSERT_WITH_SECURITY_IMPLICATION(i < maxDepth); return m_data[i]; } void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; } void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; } diff --git a/Source/WTF/wtf/Alignment.h b/Source/WTF/wtf/Alignment.h index 7dfda209a..50ccb02e4 100644 --- a/Source/WTF/wtf/Alignment.h +++ b/Source/WTF/wtf/Alignment.h @@ -38,7 +38,7 @@ namespace WTF { #error WTF_ALIGN macros need alignment control. #endif -#if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) +#if COMPILER(GCC) && !COMPILER(INTEL) typedef char __attribute__((__may_alias__)) AlignedBufferChar; #else typedef char AlignedBufferChar; diff --git a/Source/WTF/wtf/AlwaysInline.h b/Source/WTF/wtf/AlwaysInline.h deleted file mode 100644 index 68b7ae1a8..000000000 --- a/Source/WTF/wtf/AlwaysInline.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -/* This file is no longer necessary, since all the functionality has been moved to Compiler.h. */ - -#include <wtf/Platform.h> diff --git a/Source/WTF/wtf/ArrayBuffer.cpp b/Source/WTF/wtf/ArrayBuffer.cpp index 45cfa1deb..45b57fe9c 100644 --- a/Source/WTF/wtf/ArrayBuffer.cpp +++ b/Source/WTF/wtf/ArrayBuffer.cpp @@ -42,12 +42,25 @@ bool ArrayBuffer::transfer(ArrayBufferContents& result, Vector<RefPtr<ArrayBuffe return false; } - m_contents.transfer(result); + bool allViewsAreNeuterable = true; + for (ArrayBufferView* i = m_firstView; i; i = i->m_nextView) { + if (!i->isNeuterable()) + allViewsAreNeuterable = false; + } + + if (allViewsAreNeuterable) + m_contents.transfer(result); + else { + m_contents.copyTo(result); + if (!result.m_data) + return false; + } while (m_firstView) { ArrayBufferView* current = m_firstView; removeView(current); - current->neuter(); + if (allViewsAreNeuterable || current->isNeuterable()) + current->neuter(); neuteredViews.append(current); } return true; diff --git a/Source/WTF/wtf/ArrayBuffer.h b/Source/WTF/wtf/ArrayBuffer.h index aa59cf733..3e0a1b3c3 100644 --- a/Source/WTF/wtf/ArrayBuffer.h +++ b/Source/WTF/wtf/ArrayBuffer.h @@ -36,25 +36,12 @@ namespace WTF { class ArrayBuffer; class ArrayBufferView; -#if defined(WTF_USE_V8) -// The current implementation assumes that the instance of this class is a -// singleton living for the entire process's lifetime. -class ArrayBufferDeallocationObserver { -public: - virtual void ArrayBufferDeallocated(unsigned sizeInBytes) = 0; -}; -#endif - - class ArrayBufferContents { WTF_MAKE_NONCOPYABLE(ArrayBufferContents); public: ArrayBufferContents() : m_data(0) , m_sizeInBytes(0) -#if defined(WTF_USE_V8) - , m_deallocationObserver(0) -#endif { } inline ~ArrayBufferContents(); @@ -66,9 +53,6 @@ private: ArrayBufferContents(void* data, unsigned sizeInBytes) : m_data(data) , m_sizeInBytes(sizeInBytes) -#if defined(WTF_USE_V8) - , m_deallocationObserver(0) -#endif { } friend class ArrayBuffer; @@ -86,21 +70,20 @@ private: other.m_sizeInBytes = m_sizeInBytes; m_data = 0; m_sizeInBytes = 0; -#if defined(WTF_USE_V8) - // Notify the current V8 isolate that the buffer is gone. - if (m_deallocationObserver) - m_deallocationObserver->ArrayBufferDeallocated(other.m_sizeInBytes); - ASSERT(!other.m_deallocationObserver); - m_deallocationObserver = 0; -#endif + } + + void copyTo(ArrayBufferContents& other) + { + ASSERT(!other.m_data); + ArrayBufferContents::tryAllocate(m_sizeInBytes, sizeof(char), ArrayBufferContents::DontInitialize, other); + if (!other.m_data) + return; + memcpy(other.m_data, m_data, m_sizeInBytes); + other.m_sizeInBytes = m_sizeInBytes; } void* m_data; unsigned m_sizeInBytes; - -#if defined(WTF_USE_V8) - ArrayBufferDeallocationObserver* m_deallocationObserver; -#endif }; class ArrayBuffer : public RefCounted<ArrayBuffer> { @@ -126,13 +109,6 @@ public: WTF_EXPORT_PRIVATE bool transfer(ArrayBufferContents&, Vector<RefPtr<ArrayBufferView> >& neuteredViews); bool isNeutered() { return !m_contents.m_data; } -#if defined(WTF_USE_V8) - void setDeallocationObserver(ArrayBufferDeallocationObserver* deallocationObserver) - { - m_contents.m_deallocationObserver = deallocationObserver; - } -#endif - ~ArrayBuffer() { } private: @@ -272,10 +248,6 @@ void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByte ArrayBufferContents::~ArrayBufferContents() { -#if defined (WTF_USE_V8) - if (m_deallocationObserver) - m_deallocationObserver->ArrayBufferDeallocated(m_sizeInBytes); -#endif WTF::fastFree(m_data); } diff --git a/Source/WTF/wtf/ArrayBufferView.cpp b/Source/WTF/wtf/ArrayBufferView.cpp index 66759de0b..202b3a2e4 100644 --- a/Source/WTF/wtf/ArrayBufferView.cpp +++ b/Source/WTF/wtf/ArrayBufferView.cpp @@ -33,6 +33,7 @@ namespace WTF { ArrayBufferView::ArrayBufferView(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset) : m_byteOffset(byteOffset) + , m_isNeuterable(true) , m_buffer(buffer) , m_prevView(0) , m_nextView(0) diff --git a/Source/WTF/wtf/ArrayBufferView.h b/Source/WTF/wtf/ArrayBufferView.h index 451c1b6ed..3b708fbdf 100644 --- a/Source/WTF/wtf/ArrayBufferView.h +++ b/Source/WTF/wtf/ArrayBufferView.h @@ -36,7 +36,7 @@ namespace WTF { -class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferView> { +class ArrayBufferView : public RefCounted<ArrayBufferView> { public: enum ViewType { TypeInt8, @@ -69,10 +69,13 @@ class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferVie virtual unsigned byteLength() const = 0; - WTF_EXPORT_PRIVATE_NO_RTTI virtual ~ArrayBufferView(); + void setNeuterable(bool flag) { m_isNeuterable = flag; } + bool isNeuterable() const { return m_isNeuterable; } + + WTF_EXPORT_PRIVATE virtual ~ArrayBufferView(); protected: - WTF_EXPORT_PRIVATE_NO_RTTI ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset); + WTF_EXPORT_PRIVATE ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset); inline bool setImpl(ArrayBufferView*, unsigned byteOffset); @@ -122,12 +125,13 @@ class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferVie *numElements = std::min(remainingElements, *numElements); } - WTF_EXPORT_PRIVATE_NO_RTTI virtual void neuter(); + WTF_EXPORT_PRIVATE virtual void neuter(); // This is the address of the ArrayBuffer's storage, plus the byte offset. void* m_baseAddress; - unsigned m_byteOffset; + unsigned m_byteOffset : 31; + bool m_isNeuterable : 1; private: friend class ArrayBuffer; diff --git a/Source/WTF/wtf/Assertions.cpp b/Source/WTF/wtf/Assertions.cpp index ed48d813d..f462a3ffd 100644 --- a/Source/WTF/wtf/Assertions.cpp +++ b/Source/WTF/wtf/Assertions.cpp @@ -45,10 +45,13 @@ #include <signal.h> #endif -#if PLATFORM(MAC) +#if USE(CF) #include <CoreFoundation/CFString.h> +#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#define WTF_USE_APPLE_SYSTEM_LOG 1 #include <asl.h> #endif +#endif // USE(CF) #if COMPILER(MSVC) && !OS(WINCE) #include <crtdbg.h> @@ -58,16 +61,12 @@ #include <windows.h> #endif -#if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID) +#if OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__)) #include <cxxabi.h> #include <dlfcn.h> #include <execinfo.h> #endif -#if OS(ANDROID) -#include "android/log.h" -#endif - #if PLATFORM(BLACKBERRY) #include <BlackBerryPlatformLog.h> #endif @@ -77,7 +76,7 @@ extern "C" { WTF_ATTRIBUTE_PRINTF(1, 0) static void vprintf_stderr_common(const char* format, va_list args) { -#if PLATFORM(MAC) +#if USE(CF) && !OS(WINDOWS) if (strstr(format, "%@")) { CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); @@ -89,12 +88,12 @@ static void vprintf_stderr_common(const char* format, va_list args) #if COMPILER(CLANG) #pragma clang diagnostic pop #endif - int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); + CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char* buffer = (char*)malloc(length + 1); CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); -#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#if USE(APPLE_SYSTEM_LOG) asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer); #endif fputs(buffer, stderr); @@ -105,7 +104,7 @@ static void vprintf_stderr_common(const char* format, va_list args) return; } -#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#if USE(APPLE_SYSTEM_LOG) va_list copyOfArgs; va_copy(copyOfArgs, args); asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs); @@ -116,8 +115,6 @@ static void vprintf_stderr_common(const char* format, va_list args) #elif PLATFORM(BLACKBERRY) BBLOGV(BlackBerry::Platform::LogLevelCritical, format, args); -#elif OS(ANDROID) - __android_log_vprint(ANDROID_LOG_WARN, "WebKit", format, args); #elif HAVE(ISDEBUGGERPRESENT) if (IsDebuggerPresent()) { size_t size = 1024; @@ -242,7 +239,7 @@ void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f void WTFGetBacktrace(void** stack, int* size) { -#if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID) +#if OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__)) *size = backtrace(stack, *size); #elif OS(WINDOWS) && !OS(WINCE) // The CaptureStackBackTrace function is available in XP, but it is not defined @@ -281,7 +278,7 @@ void WTFReportBacktrace() # if defined(__GLIBC__) && !defined(__UCLIBC__) # define WTF_USE_BACKTRACE_SYMBOLS 1 # endif -# elif !OS(ANDROID) +# else # define WTF_USE_DLADDR 1 # endif #endif @@ -331,8 +328,21 @@ void WTFSetCrashHook(WTFCrashHookFunction function) void WTFInvokeCrashHook() { +} + +void WTFCrash() +{ if (globalHook) globalHook(); + + WTFReportBacktrace(); + *(int *)(uintptr_t)0xbbadbeef = 0; + // More reliable, but doesn't say BBADBEEF. +#if COMPILER(CLANG) + __builtin_trap(); +#else + ((void(*)())0)(); +#endif } #if HAVE(SIGNAL_H) diff --git a/Source/WTF/wtf/Assertions.h b/Source/WTF/wtf/Assertions.h index 7e079ab18..b8ac68faa 100644 --- a/Source/WTF/wtf/Assertions.h +++ b/Source/WTF/wtf/Assertions.h @@ -34,12 +34,6 @@ For non-debug builds, everything is disabled by default. Defining any of the symbols explicitly prevents this from having any effect. - - MSVC7 note: variadic macro support was added in MSVC8, so for now we disable - those macros in MSVC7. For more info, see the MSDN document on variadic - macros here: - - http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx */ #include <wtf/Platform.h> @@ -57,12 +51,6 @@ #define ASSERTIONS_DISABLED_DEFAULT 0 #endif -#if COMPILER(MSVC7_OR_LOWER) -#define HAVE_VARIADIC_MACRO 0 -#else -#define HAVE_VARIADIC_MACRO 1 -#endif - #ifndef BACKTRACE_DISABLED #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT #endif @@ -72,11 +60,7 @@ #endif #ifndef ASSERT_MSG_DISABLED -#if HAVE(VARIADIC_MACRO) #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define ASSERT_MSG_DISABLED 1 -#endif #endif #ifndef ASSERT_ARG_DISABLED @@ -84,27 +68,15 @@ #endif #ifndef FATAL_DISABLED -#if HAVE(VARIADIC_MACRO) #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define FATAL_DISABLED 1 -#endif #endif #ifndef ERROR_DISABLED -#if HAVE(VARIADIC_MACRO) #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define ERROR_DISABLED 1 -#endif #endif #ifndef LOG_DISABLED -#if HAVE(VARIADIC_MACRO) #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define LOG_DISABLED 1 -#endif #endif #if COMPILER(GCC) @@ -151,9 +123,10 @@ WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size); typedef void (*WTFCrashHookFunction)(); WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction); -WTF_EXPORT_PRIVATE void WTFInvokeCrashHook(); WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook(); +// Exist for binary compatibility with older Safari. Do not use. +WTF_EXPORT_PRIVATE void WTFInvokeCrashHook(); #ifdef __cplusplus } #endif @@ -166,29 +139,23 @@ WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook(); Signals are ignored by the crash reporter on OS X so we must do better. */ -#ifndef CRASH -#if COMPILER(CLANG) -#define CRASH() \ - (WTFReportBacktrace(), \ - WTFInvokeCrashHook(), \ - (*(int *)(uintptr_t)0xbbadbeef = 0), \ - __builtin_trap()) -#else -#define CRASH() \ - (WTFReportBacktrace(), \ - WTFInvokeCrashHook(), \ - (*(int *)(uintptr_t)0xbbadbeef = 0), \ - ((void(*)())0)() /* More reliable, but doesn't say BBADBEEF */ \ - ) -#endif -#endif - #if COMPILER(CLANG) #define NO_RETURN_DUE_TO_CRASH NO_RETURN #else #define NO_RETURN_DUE_TO_CRASH #endif +#ifndef CRASH +#define CRASH() WTFCrash() +#endif + +#ifdef __cplusplus +extern "C" { +#endif +WTF_EXPORT_PRIVATE void WTFCrash() NO_RETURN_DUE_TO_CRASH; +#ifdef __cplusplus +} +#endif /* BACKTRACE @@ -213,7 +180,7 @@ WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook(); Expressions inside them are evaluated in debug builds only. */ -#if OS(WINCE) && !PLATFORM(TORCHMOBILE) +#if OS(WINCE) /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */ #include <windows.h> #undef min @@ -266,11 +233,31 @@ inline void assertUnused(T& x) { (void)x; } #endif +/* ASSERT_WITH_SECURITY_IMPLICATION + + Failure of this assertion indicates a possible security vulnerability. + Class of vulnerabilities that it tests include bad casts, out of bounds + accesses, use-after-frees, etc. Please file a bug using the security + template - https://bugs.webkit.org/enter_bug.cgi?product=Security. + +*/ +#ifdef ADDRESS_SANITIZER + +#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \ + (!(assertion) ? \ + (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \ + CRASH()) : \ + (void)0) + +#else + +#define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT(assertion) + +#endif + /* ASSERT_WITH_MESSAGE */ -#if COMPILER(MSVC7_OR_LOWER) -#define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif ASSERT_MSG_DISABLED +#if ASSERT_MSG_DISABLED #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) do \ @@ -283,9 +270,7 @@ while (0) /* ASSERT_WITH_MESSAGE_UNUSED */ -#if COMPILER(MSVC7_OR_LOWER) -#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion) ((void)0) -#elif ASSERT_MSG_DISABLED +#if ASSERT_MSG_DISABLED #if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) template<typename T> inline void assertWithMessageUnused(T& x) { (void)x; } @@ -323,7 +308,10 @@ while (0) /* COMPILE_ASSERT */ #ifndef COMPILE_ASSERT #if COMPILER_SUPPORTS(C_STATIC_ASSERT) +/* Unlike static_assert below, this also works in plain C code. */ #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name) +#elif COMPILER_SUPPORTS(CXX_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 @@ -331,9 +319,7 @@ while (0) /* FATAL */ -#if COMPILER(MSVC7_OR_LOWER) -#define FATAL() ((void)0) -#elif FATAL_DISABLED +#if FATAL_DISABLED #define FATAL(...) ((void)0) #else #define FATAL(...) do { \ @@ -344,9 +330,7 @@ while (0) /* LOG_ERROR */ -#if COMPILER(MSVC7_OR_LOWER) -#define LOG_ERROR() ((void)0) -#elif ERROR_DISABLED +#if ERROR_DISABLED #define LOG_ERROR(...) ((void)0) #else #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) @@ -354,9 +338,7 @@ while (0) /* LOG */ -#if COMPILER(MSVC7_OR_LOWER) -#define LOG() ((void)0) -#elif LOG_DISABLED +#if LOG_DISABLED #define LOG(channel, ...) ((void)0) #else #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) @@ -366,9 +348,7 @@ while (0) /* LOG_VERBOSE */ -#if COMPILER(MSVC7_OR_LOWER) -#define LOG_VERBOSE(channel) ((void)0) -#elif LOG_DISABLED +#if LOG_DISABLED #define LOG_VERBOSE(channel, ...) ((void)0) #else #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) @@ -390,4 +370,14 @@ static inline void UNREACHABLE_FOR_PLATFORM() #define UNREACHABLE_FOR_PLATFORM() ASSERT_NOT_REACHED() #endif +#if ASSERT_DISABLED +#define RELEASE_ASSERT(assertion) (UNLIKELY(!(assertion)) ? (CRASH()) : (void)0) +#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion) +#define RELEASE_ASSERT_NOT_REACHED() CRASH() +#else +#define RELEASE_ASSERT(assertion) ASSERT(assertion) +#define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__) +#define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED() +#endif + #endif /* WTF_Assertions_h */ diff --git a/Source/WTF/wtf/Atomics.cpp b/Source/WTF/wtf/Atomics.cpp index edb8fae95..0feea1532 100644 --- a/Source/WTF/wtf/Atomics.cpp +++ b/Source/WTF/wtf/Atomics.cpp @@ -7,13 +7,13 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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. + * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -32,14 +32,14 @@ * is virtually identical to the Apple license above but is included here for completeness. * * Boost Software License - Version 1.0 - August 17th, 2003 - * + * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: - * + * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and diff --git a/Source/WTF/wtf/Atomics.h b/Source/WTF/wtf/Atomics.h index d6cd88d88..a12cfd0b4 100644 --- a/Source/WTF/wtf/Atomics.h +++ b/Source/WTF/wtf/Atomics.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2010, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) * * Redistribution and use in source and binary forms, with or without @@ -61,14 +61,17 @@ #include <wtf/Platform.h> #include <wtf/StdLibExtras.h> -#include <wtf/UnusedParam.h> #if OS(WINDOWS) +#if OS(WINCE) +#include <cmnintrin.h> +#else +extern "C" void _ReadWriteBarrier(void); +#pragma intrinsic(_ReadWriteBarrier) +#endif #include <windows.h> #elif OS(QNX) #include <atomic.h> -#elif OS(ANDROID) -#include <sys/atomics.h> #endif namespace WTF { @@ -76,12 +79,21 @@ namespace WTF { #if OS(WINDOWS) #define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 -#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) +#if OS(WINCE) inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } +#elif COMPILER(MINGW) +inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } +inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } + +inline int64_t atomicIncrement(int64_t* addend) { return InterlockedIncrement64(reinterpret_cast<long long*>(addend)); } +inline int64_t atomicDecrement(int64_t* addend) { return InterlockedDecrement64(reinterpret_cast<long long*>(addend)); } #else inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); } inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); } + +inline int64_t atomicIncrement(int64_t volatile* addend) { return InterlockedIncrement64(reinterpret_cast<long long volatile*>(addend)); } +inline int64_t atomicDecrement(int64_t volatile* addend) { return InterlockedDecrement64(reinterpret_cast<long long volatile*>(addend)); } #endif #elif OS(QNX) @@ -91,13 +103,6 @@ inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(r inline int atomicIncrement(int volatile* addend) { return static_cast<int>(atomic_add_value(reinterpret_cast<unsigned volatile*>(addend), 1)) + 1; } inline int atomicDecrement(int volatile* addend) { return static_cast<int>(atomic_sub_value(reinterpret_cast<unsigned volatile*>(addend), 1)) - 1; } -#elif OS(ANDROID) -#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 - -// Note, __atomic_{inc, dec}() return the previous value of addend's content. -inline int atomicIncrement(int volatile* addend) { return __atomic_inc(addend) + 1; } -inline int atomicDecrement(int volatile* addend) { return __atomic_dec(addend) - 1; } - #elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc #define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 @@ -198,22 +203,70 @@ inline bool weakCompareAndSwapUIntPtr(volatile uintptr_t* location, uintptr_t ex return weakCompareAndSwap(reinterpret_cast<void*volatile*>(location), reinterpret_cast<void*>(expected), reinterpret_cast<void*>(newValue)); } +// Just a compiler fence. Has no effect on the hardware, but tells the compiler +// not to move things around this call. Should not affect the compiler's ability +// to do things like register allocation and code motion over pure operations. +inline void compilerFence() +{ +#if OS(WINDOWS) + _ReadWriteBarrier(); +#else + asm volatile("" ::: "memory"); +#endif +} + #if CPU(ARM_THUMB2) -inline void memoryBarrierAfterLock() +// Full memory fence. No accesses will float above this, and no accesses will sink +// below it. +inline void armV7_dmb() { asm volatile("dmb" ::: "memory"); } -inline void memoryBarrierBeforeUnlock() +// Like the above, but only affects stores. +inline void armV7_dmb_st() { - asm volatile("dmb" ::: "memory"); + asm volatile("dmb st" ::: "memory"); } +inline void loadLoadFence() { armV7_dmb(); } +inline void loadStoreFence() { armV7_dmb(); } +inline void storeLoadFence() { armV7_dmb(); } +inline void storeStoreFence() { armV7_dmb_st(); } +inline void memoryBarrierAfterLock() { armV7_dmb(); } +inline void memoryBarrierBeforeUnlock() { armV7_dmb(); } + +#elif CPU(X86) || CPU(X86_64) + +inline void x86_mfence() +{ +#if OS(WINDOWS) + // I think that this does the equivalent of a dummy interlocked instruction, + // instead of using the 'mfence' instruction, at least according to MSDN. I + // know that it is equivalent for our purposes, but it would be good to + // investigate if that is actually better. + MemoryBarrier(); +#else + asm volatile("mfence" ::: "memory"); +#endif +} + +inline void loadLoadFence() { compilerFence(); } +inline void loadStoreFence() { compilerFence(); } +inline void storeLoadFence() { x86_mfence(); } +inline void storeStoreFence() { compilerFence(); } +inline void memoryBarrierAfterLock() { compilerFence(); } +inline void memoryBarrierBeforeUnlock() { compilerFence(); } + #else -inline void memoryBarrierAfterLock() { } -inline void memoryBarrierBeforeUnlock() { } +inline void loadLoadFence() { compilerFence(); } +inline void loadStoreFence() { compilerFence(); } +inline void storeLoadFence() { compilerFence(); } +inline void storeStoreFence() { compilerFence(); } +inline void memoryBarrierAfterLock() { compilerFence(); } +inline void memoryBarrierBeforeUnlock() { compilerFence(); } #endif diff --git a/Source/WTF/wtf/wx/MainThreadWx.cpp b/Source/WTF/wtf/AutodrainedPool.h index e1d15c96f..2448eea11 100644 --- a/Source/WTF/wtf/wx/MainThreadWx.cpp +++ b/Source/WTF/wtf/AutodrainedPool.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Kevin Ollivier + * Copyright (C) 2007, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,41 +26,34 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "MainThread.h" +#ifndef AutodrainedPool_h +#define AutodrainedPool_h -#include <wx/defs.h> -#include <wx/app.h> -#include <wx/event.h> +#include <wtf/Noncopyable.h> -const wxEventType wxEVT_CALL_AFTER = wxNewEventType(); +OBJC_CLASS NSAutoreleasePool; -class wxCallAfter : public wxEvtHandler -{ +namespace WTF { + +class AutodrainedPool { + WTF_MAKE_NONCOPYABLE(AutodrainedPool); public: - wxCallAfter() - : wxEvtHandler() - { - wxTheApp->Connect(-1, -1, wxEVT_CALL_AFTER, wxCommandEventHandler(wxCallAfter::OnCallback)); - wxCommandEvent event(wxEVT_CALL_AFTER); - wxPostEvent(wxTheApp, event); - } - - void OnCallback(wxCommandEvent& event) - { - WTF::dispatchFunctionsFromMainThread(); - } +#if PLATFORM(MAC) + WTF_EXPORT_PRIVATE AutodrainedPool(); + WTF_EXPORT_PRIVATE ~AutodrainedPool(); +#else + explicit AutodrainedPool() { } + ~AutodrainedPool() { } +#endif + +private: +#if PLATFORM(MAC) + NSAutoreleasePool* m_pool; +#endif }; -namespace WTF { - -void initializeMainThreadPlatform() -{ -} +} // namespace WTF -void scheduleDispatchFunctionsOnMainThread() -{ - wxCallAfter(); -} +using WTF::AutodrainedPool; -} // namespace WTF +#endif diff --git a/Source/WTF/wtf/MallocZoneSupport.h b/Source/WTF/wtf/AutodrainedPoolMac.mm index 4332e40b8..b1f44aa11 100644 --- a/Source/WTF/wtf/MallocZoneSupport.h +++ b/Source/WTF/wtf/AutodrainedPoolMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,48 +26,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MallocZoneSupport_h -#define MallocZoneSupport_h +#import "config.h" +#import "AutodrainedPool.h" -#include <malloc/malloc.h> +#import <Foundation/Foundation.h> namespace WTF { -class RemoteMemoryReader { - task_t m_task; - memory_reader_t* m_reader; +AutodrainedPool::AutodrainedPool() + : m_pool([[NSAutoreleasePool alloc] init]) +{ +} -public: - RemoteMemoryReader(task_t task, memory_reader_t* reader) - : m_task(task) - , m_reader(reader) - { } - - void* operator()(vm_address_t address, size_t size) const - { - void* output; - kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output)); - if (err) - output = 0; - return output; - } - - template <typename T> - T* operator()(T* address, size_t size=sizeof(T)) const - { - return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size)); - } - - template <typename T> - T* nextEntryInLinkedList(T** address) const - { - T** output = (*this)(address); - if (!output) - return 0; - return *output; - } -}; +AutodrainedPool::~AutodrainedPool() +{ + [m_pool drain]; +} } // namespace WTF - -#endif // MallocZoneSupport_h diff --git a/Source/WTF/wtf/BitArray.h b/Source/WTF/wtf/BitArray.h index b1ef2276f..9ad1e0a1f 100644 --- a/Source/WTF/wtf/BitArray.h +++ b/Source/WTF/wtf/BitArray.h @@ -41,13 +41,13 @@ public: void set(unsigned index) { - ASSERT(index < arraySize); + ASSERT_WITH_SECURITY_IMPLICATION(index < arraySize); m_data[index / 8] |= 1 << (index & 7); } bool get(unsigned index) const { - ASSERT(index < arraySize); + ASSERT_WITH_SECURITY_IMPLICATION(index < arraySize); return !!(m_data[index / 8] & (1 << (index & 7))); } diff --git a/Source/WTF/wtf/BitVector.h b/Source/WTF/wtf/BitVector.h index 1673ac58b..f42bc0b91 100644 --- a/Source/WTF/wtf/BitVector.h +++ b/Source/WTF/wtf/BitVector.h @@ -111,19 +111,19 @@ public: bool quickGet(size_t bit) const { - ASSERT(bit < size()); + ASSERT_WITH_SECURITY_IMPLICATION(bit < size()); return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)))); } void quickSet(size_t bit) { - ASSERT(bit < size()); + ASSERT_WITH_SECURITY_IMPLICATION(bit < size()); bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); } void quickClear(size_t bit) { - ASSERT(bit < size()); + ASSERT_WITH_SECURITY_IMPLICATION(bit < size()); bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); } diff --git a/Source/WTF/wtf/BloomFilter.h b/Source/WTF/wtf/BloomFilter.h index f81d83e21..47628fdce 100644 --- a/Source/WTF/wtf/BloomFilter.h +++ b/Source/WTF/wtf/BloomFilter.h @@ -26,7 +26,6 @@ #ifndef BloomFilter_h #define BloomFilter_h -#include <wtf/AlwaysInline.h> #include <wtf/text/AtomicString.h> namespace WTF { @@ -36,6 +35,7 @@ namespace WTF { // keys and m is the table size (==2^keyBits). template <unsigned keyBits> class BloomFilter { + WTF_MAKE_FAST_ALLOCATED; public: COMPILE_ASSERT(keyBits <= 16, bloom_filter_key_size); diff --git a/Source/WTF/wtf/BoundsCheckedPointer.h b/Source/WTF/wtf/BoundsCheckedPointer.h index 1f7caab63..be0d21a2c 100644 --- a/Source/WTF/wtf/BoundsCheckedPointer.h +++ b/Source/WTF/wtf/BoundsCheckedPointer.h @@ -30,7 +30,6 @@ #define WTF_BoundsCheckedPointer_h #include <wtf/Assertions.h> -#include <wtf/UnusedParam.h> namespace WTF { diff --git a/Source/WTF/wtf/ByteOrder.h b/Source/WTF/wtf/ByteOrder.h index 08e3783fb..9d96ea6ed 100644 --- a/Source/WTF/wtf/ByteOrder.h +++ b/Source/WTF/wtf/ByteOrder.h @@ -51,7 +51,7 @@ inline uint16_t htons(uint16_t x) { return x; } inline uint32_t ntohl(uint32_t x) { return x; } inline uint32_t htonl(uint32_t x) { return x; } #elif CPU(MIDDLE_ENDIAN) -inline uint16_t ntohs(unit16_t x) { return x; } +inline uint16_t ntohs(uint16_t x) { return x; } inline uint16_t htons(uint16_t x) { return x; } inline uint32_t ntohl(uint32_t x) { return WTF::wswap32(x); } inline uint32_t htonl(uint32_t x) { return WTF::wswap32(x); } diff --git a/Source/WTF/wtf/CMakeLists.txt b/Source/WTF/wtf/CMakeLists.txt index b7f437c64..8667f12eb 100644 --- a/Source/WTF/wtf/CMakeLists.txt +++ b/Source/WTF/wtf/CMakeLists.txt @@ -1,8 +1,7 @@ -SET(WTF_HEADERS +set(WTF_HEADERS ASCIICType.h AVLTree.h Alignment.h - AlwaysInline.h Assertions.h Atomics.h BitArray.h @@ -12,7 +11,6 @@ SET(WTF_HEADERS BumpPointerAllocator.h ByteOrder.h Compiler.h - Complex.h CryptographicallyRandomNumber.h CurrentTime.h DateMath.h @@ -26,9 +24,12 @@ SET(WTF_HEADERS Encoder.h FastAllocBase.h FastMalloc.h + FeatureDefines.h FilePrintStream.h FixedArray.h Forward.h + FunctionDispatcher.h + Functional.h GetPtr.h GregorianDateTime.h HashCountedSet.h @@ -40,24 +41,11 @@ SET(WTF_HEADERS HashTraits.h HexNumber.h ListHashSet.h - ListRefPtr.h Locker.h MD5.h MainThread.h - MallocZoneSupport.h MathExtras.h MediaTime.h - MemoryInstrumentation.h - MemoryInstrumentationArrayBufferView.h - MemoryInstrumentationHashCountedSet.h - MemoryInstrumentationHashMap.h - MemoryInstrumentationHashSet.h - MemoryInstrumentationListHashSet.h - MemoryInstrumentationParsedURL.h - MemoryInstrumentationSequence.h - MemoryInstrumentationString.h - MemoryInstrumentationVector.h - MemoryObjectInfo.h MessageQueue.h MetaAllocator.h MetaAllocatorHandle.h @@ -88,6 +76,7 @@ SET(WTF_HEADERS Platform.h PossiblyNull.h PrintStream.h + ProcessID.h RandomNumber.h RandomNumberSeed.h RawPointer.h @@ -116,12 +105,12 @@ SET(WTF_HEADERS Threading.h ThreadingPrimitives.h TypeTraits.h - UnusedParam.h VMTags.h ValueCheck.h Vector.h VectorTraits.h WTFThreadData.h + WeakPtr.h dtoa.h dtoa/bignum-dtoa.h @@ -137,6 +126,7 @@ SET(WTF_HEADERS text/AtomicString.h text/AtomicStringImpl.h + text/AtomicStringTable.h text/Base64.h text/CString.h text/IntegerToStringConversion.h @@ -153,7 +143,7 @@ SET(WTF_HEADERS unicode/Unicode.h ) -SET(WTF_SOURCES +set(WTF_SOURCES ArrayBuffer.cpp ArrayBufferView.cpp Assertions.cpp @@ -167,14 +157,15 @@ SET(WTF_SOURCES DynamicAnnotations.cpp FastMalloc.cpp FilePrintStream.cpp + FunctionDispatcher.cpp GregorianDateTime.cpp HashTable.cpp MD5.cpp MainThread.cpp MediaTime.cpp MetaAllocator.cpp + NullPtr.cpp OSRandomSource.cpp - MemoryInstrumentation.cpp NumberOfCores.cpp RAMSize.cpp PageAllocationAligned.cpp @@ -185,8 +176,8 @@ SET(WTF_SOURCES RefCountedLeakCounter.cpp SHA1.cpp StackBounds.cpp - StringExtras.cpp StringPrintStream.cpp + TCSystemAlloc.cpp Threading.cpp TypeTraits.cpp WTFThreadData.cpp @@ -202,6 +193,7 @@ SET(WTF_SOURCES dtoa/strtod.cc text/AtomicString.cpp + text/AtomicStringTable.cpp text/Base64.cpp text/CString.cpp text/StringBuilder.cpp @@ -214,7 +206,7 @@ SET(WTF_SOURCES unicode/UTF8.cpp ) -SET(WTF_INCLUDE_DIRECTORIES +set(WTF_INCLUDE_DIRECTORIES "${WTF_DIR}" "${WTF_DIR}/wtf" "${WTF_DIR}/wtf/dtoa" @@ -224,17 +216,62 @@ SET(WTF_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}" ) -IF (NOT USE_SYSTEM_MALLOC) - LIST(APPEND WTF_SOURCES - TCSystemAlloc.cpp +set(WTF_LIBRARIES + ${CMAKE_DL_LIBS} +) + +if (WTF_USE_ICU_UNICODE) + list(APPEND WTF_HEADERS + unicode/icu/UnicodeIcu.h + ) + list(APPEND WTF_SOURCES + unicode/icu/CollatorICU.cpp + ) + list(APPEND WTF_INCLUDE_DIRECTORIES + ${ICU_INCLUDE_DIRS} + ) + list(APPEND WTF_LIBRARIES + ${ICU_I18N_LIBRARIES} + ${ICU_LIBRARIES} + ) +elseif (WTF_USE_WCHAR_UNICODE) + list(APPEND WTF_HEADERS + unicode/wchar/UnicodeWchar.h + ) + list(APPEND WTF_SOURCES + unicode/CollatorDefault.cpp + unicode/wchar/UnicodeWchar.cpp ) -ENDIF() +endif () + +if (WIN32) + list(APPEND WTF_SOURCES + OSAllocatorWin.cpp + ThreadSpecificWin.cpp + ThreadingWin.cpp + + win/OwnPtrWin.cpp + ) +else () + list(APPEND WTF_HEADERS + ThreadIdentifierDataPthreads.h + ) + list(APPEND WTF_SOURCES + OSAllocatorPosix.cpp + ThreadIdentifierDataPthreads.cpp + ThreadingPthreads.cpp + ) +endif () WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() WEBKIT_WRAP_SOURCELIST(${WTF_SOURCES}) -INCLUDE_DIRECTORIES(${WTF_INCLUDE_DIRECTORIES}) -ADD_DEFINITIONS(-DBUILDING_WTF) -ADD_LIBRARY(${WTF_LIBRARY_NAME} STATIC ${WTF_HEADERS} ${WTF_SOURCES}) -TARGET_LINK_LIBRARIES(${WTF_LIBRARY_NAME} ${WTF_LIBRARIES}) -SET_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} PROPERTIES FOLDER "JavaScriptCore") +include_directories(${WTF_INCLUDE_DIRECTORIES}) +add_definitions(-DBUILDING_WTF) +add_library(WTF STATIC ${WTF_HEADERS} ${WTF_SOURCES}) +target_link_libraries(WTF ${WTF_LIBRARIES}) +set_target_properties(WTF PROPERTIES FOLDER "JavaScriptCore") + +if (WTF_OUTPUT_NAME) + set_target_properties(WTF PROPERTIES OUTPUT_NAME ${WTF_OUTPUT_NAME}) +endif () diff --git a/Source/WTF/wtf/CheckedArithmetic.h b/Source/WTF/wtf/CheckedArithmetic.h index f5d3b7550..dd4acbb9b 100644 --- a/Source/WTF/wtf/CheckedArithmetic.h +++ b/Source/WTF/wtf/CheckedArithmetic.h @@ -27,6 +27,7 @@ #define CheckedArithmetic_h #include <wtf/Assertions.h> +#include <wtf/EnumClass.h> #include <wtf/TypeTraits.h> #include <limits> @@ -66,9 +67,15 @@ namespace WTF { +ENUM_CLASS(CheckedState) +{ + DidOverflow, + DidNotOverflow +} ENUM_CLASS_END(CheckedState); + class CrashOnOverflow { -protected: - NO_RETURN_DUE_TO_CRASH void overflowed() +public: + static NO_RETURN_DUE_TO_CRASH void overflowed() { CRASH(); } @@ -314,10 +321,13 @@ template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOper static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN { - ResultType temp = lhs * rhs; - if (temp < lhs) + if (!lhs || !rhs) { + result = 0; + return true; + } + if (std::numeric_limits<ResultType>::max() / lhs < rhs) return false; - result = temp; + result = lhs * rhs; return true; } @@ -534,10 +544,12 @@ public: return m_value; } - bool safeGet(T& value) const WARN_UNUSED_RETURN + inline CheckedState safeGet(T& value) const WARN_UNUSED_RETURN { value = m_value; - return this->hasOverflowed(); + if (this->hasOverflowed()) + return CheckedState::DidOverflow; + return CheckedState::DidNotOverflow; } // Mutating assignment @@ -638,7 +650,7 @@ template <typename U, typename V, typename OverflowHandler> static inline Checke { U x = 0; V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; typename Result<U, V>::ResultType result = 0; overflowed |= !safeAdd(x, y, result); if (overflowed) @@ -650,7 +662,7 @@ template <typename U, typename V, typename OverflowHandler> static inline Checke { U x = 0; V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; typename Result<U, V>::ResultType result = 0; overflowed |= !safeSub(x, y, result); if (overflowed) @@ -662,7 +674,7 @@ template <typename U, typename V, typename OverflowHandler> static inline Checke { U x = 0; V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow; typename Result<U, V>::ResultType result = 0; overflowed |= !safeMultiply(x, y, result); if (overflowed) @@ -703,6 +715,7 @@ template <typename U, typename V, typename OverflowHandler> static inline Checke } using WTF::Checked; +using WTF::CheckedState; using WTF::RecordOverflow; #endif diff --git a/Source/WTF/wtf/CheckedBoolean.h b/Source/WTF/wtf/CheckedBoolean.h index c65c70ef8..69fa8ba16 100644 --- a/Source/WTF/wtf/CheckedBoolean.h +++ b/Source/WTF/wtf/CheckedBoolean.h @@ -30,10 +30,19 @@ class CheckedBoolean { public: +#if !ASSERT_DISABLED + CheckedBoolean(const CheckedBoolean& other) + : m_value(other.m_value) + , m_checked(false) + { + other.m_checked = true; + } +#endif + CheckedBoolean(bool value) - : m_value(value) + : m_value(value) #if !ASSERT_DISABLED - , m_checked(false) + , m_checked(false) #endif { } @@ -54,7 +63,7 @@ public: private: bool m_value; #if !ASSERT_DISABLED - bool m_checked; + mutable bool m_checked; #endif }; diff --git a/Source/WTF/wtf/url/api/URLString.h b/Source/WTF/wtf/CommaPrinter.h index 70ef21910..a8f3d3917 100644 --- a/Source/WTF/wtf/url/api/URLString.h +++ b/Source/WTF/wtf/CommaPrinter.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2010 Google, Inc. All Rights Reserved. - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,44 +20,42 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef URLString_h -#define URLString_h +#ifndef CommaPrinter_h +#define CommaPrinter_h -#if USE(WTFURL) - -#include <wtf/text/WTFString.h> +#include "PrintStream.h" namespace WTF { -// URLString represents a string that's a canonicalized URL. -class URLString { +class CommaPrinter { public: - URLString() { } - - const String& string() const { return m_string;} - -#ifndef NDEBUG - WTF_EXPORT_PRIVATE void print() const; -#endif - -private: - friend class ParsedURL; - - // URLString can only be constructed by a ParsedURL. - explicit URLString(const String& string) - : m_string(string) + CommaPrinter(const char* comma = ", ") + : m_comma(comma) + , m_isFirst(true) { } - - String m_string; + + void dump(PrintStream& out) const + { + if (m_isFirst) { + m_isFirst = false; + return; + } + + out.print(m_comma); + } + +private: + const char* m_comma; + mutable bool m_isFirst; }; -} +} // namespace WTF -#endif // USE(WTFURL) +using WTF::CommaPrinter; -#endif +#endif // CommaPrinter_h diff --git a/Source/WTF/wtf/Compiler.h b/Source/WTF/wtf/Compiler.h index 293e86b8b..7a2e25f49 100644 --- a/Source/WTF/wtf/Compiler.h +++ b/Source/WTF/wtf/Compiler.h @@ -41,28 +41,26 @@ #if defined(__clang__) #define WTF_COMPILER_CLANG 1 -#ifndef __has_extension -#define __has_extension __has_feature /* Compatibility with older versions of clang */ -#endif - #define CLANG_PRAGMA(PRAGMA) _Pragma(PRAGMA) /* Specific compiler features */ -#define WTF_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES __has_extension(cxx_variadic_templates) +#define WTF_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES __has_feature(cxx_variadic_templates) /* There is a bug in clang that comes with Xcode 4.2 where AtomicStrings can't be implicitly converted to Strings in the presence of move constructors and/or move assignment operators. This bug has been fixed in Xcode 4.3 clang, so we check for both cxx_rvalue_references as well as the unrelated cxx_nonstatic_member_init feature which we know was added in 4.3 */ -#define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES __has_extension(cxx_rvalue_references) && __has_extension(cxx_nonstatic_member_init) +#define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) && __has_feature(cxx_nonstatic_member_init) -#define WTF_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS __has_extension(cxx_deleted_functions) +#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_CXX_EXPLICIT_CONVERSIONS __has_feature(cxx_explicit_conversions) #define WTF_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks) -#define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_extension(c_static_assert) -#define WTF_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL __has_extension(cxx_override_control) -#define WTF_COMPILER_SUPPORTS_HAS_TRIVIAL_DESTRUCTOR __has_extension(has_trivial_destructor) - +#define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_feature(c_static_assert) +#define WTF_COMPILER_SUPPORTS_CXX_STATIC_ASSERT __has_feature(cxx_static_assert) +#define WTF_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL __has_feature(cxx_override_control) +#define WTF_COMPILER_SUPPORTS_HAS_TRIVIAL_DESTRUCTOR __has_feature(has_trivial_destructor) +#define WTF_COMPILER_SUPPORTS_CXX_STRONG_ENUMS __has_feature(cxx_strong_enums) +#define WTF_COMPILER_SUPPORTS_CXX_REFERENCE_QUALIFIED_FUNCTIONS __has_feature(cxx_reference_qualified_functions) #endif #ifndef CLANG_PRAGMA @@ -70,13 +68,10 @@ #endif /* COMPILER(MSVC) - Microsoft Visual C++ */ -/* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/ /* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/ #if defined(_MSC_VER) #define WTF_COMPILER_MSVC 1 -#if _MSC_VER < 1400 -#define WTF_COMPILER_MSVC7_OR_LOWER 1 -#elif _MSC_VER < 1600 +#if _MSC_VER < 1600 #define WTF_COMPILER_MSVC9_OR_LOWER 1 #endif @@ -90,10 +85,15 @@ #define WTF_COMPILER_QUIRK_FINAL_IS_CALLED_SEALED 1 #endif +/* Check for VS2010 or newer */ +#if _MSC_VER >= 1600 +#define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES 1 +#define WTF_COMPILER_SUPPORTS_CXX_STATIC_ASSERT 1 #endif +#endif /* defined(_MSC_VER) */ + /* COMPILER(RVCT) - ARM RealView Compilation Tools */ -/* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */ #if defined(__CC_ARM) || defined(__ARMCC__) #define WTF_COMPILER_RVCT 1 #define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build)) @@ -124,20 +124,35 @@ #if COMPILER(GCC) && !COMPILER(CLANG) #if GCC_VERSION_AT_LEAST(4, 8, 0) #pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif -#if GCC_VERSION_AT_LEAST(4, 7, 0) && defined(__cplusplus) && __cplusplus >= 201103L +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +/* C11 support */ +#define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT 1 +#endif +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && __cplusplus >= 201103L) +/* C++11 support */ +#if GCC_VERSION_AT_LEAST(4, 3, 0) #define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES 1 +#define WTF_COMPILER_SUPPORTS_CXX_STATIC_ASSERT 1 +#define WTF_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES 1 +#endif +#if GCC_VERSION_AT_LEAST(4, 4, 0) #define WTF_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS 1 +#endif +#if GCC_VERSION_AT_LEAST(4, 5, 0) +#define WTF_COMPILER_SUPPORTS_CXX_EXPLICIT_CONVERSIONS 1 +#endif +#if GCC_VERSION_AT_LEAST(4, 6, 0) #define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 -#define WTF_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL 1 -#define WTF_COMPILER_QUIRK_GCC11_GLOBAL_ISINF_ISNAN 1 - -#elif GCC_VERSION_AT_LEAST(4, 6, 0) && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 -#define WTF_COMPILER_QUIRK_GCC11_GLOBAL_ISINF_ISNAN 1 +/* Strong enums should work from gcc 4.4, but doesn't seem to support some operators */ +#define WTF_COMPILER_SUPPORTS_CXX_STRONG_ENUMS 1 #endif - +#if GCC_VERSION_AT_LEAST(4, 7, 0) +#define WTF_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL 1 #endif +#endif /* defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && __cplusplus >= 201103L) */ +#endif /* COMPILER(GCC) */ /* COMPILER(MINGW) - MinGW GCC */ /* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */ @@ -159,8 +174,12 @@ #define WTF_COMPILER_SUNCC 1 #endif -/* ==== Compiler features ==== */ +/* ABI */ +#if defined(__ARM_EABI__) || defined(__EABI__) +#define WTF_COMPILER_SUPPORTS_EABI 1 +#endif +/* ==== Compiler features ==== */ /* ALWAYS_INLINE */ @@ -191,7 +210,7 @@ /* UNLIKELY */ #ifndef UNLIKELY -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) +#if COMPILER(GCC) || (COMPILER(RVCT) && defined(__GNUC__)) #define UNLIKELY(x) __builtin_expect((x), 0) #else #define UNLIKELY(x) (x) @@ -202,7 +221,7 @@ /* LIKELY */ #ifndef LIKELY -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) +#if COMPILER(GCC) || (COMPILER(RVCT) && defined(__GNUC__)) #define LIKELY(x) __builtin_expect((x), 1) #else #define LIKELY(x) (x) @@ -259,6 +278,12 @@ #define FINAL #endif +#if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) +#define WTF_DELETED_FUNCTION = delete +#else +#define WTF_DELETED_FUNCTION +#endif + /* REFERENCED_FROM_ASM */ #ifndef REFERENCED_FROM_ASM @@ -279,9 +304,30 @@ #endif #endif -/* ABI */ -#if defined(__ARM_EABI__) || defined(__EABI__) -#define WTF_COMPILER_SUPPORTS_EABI 1 +/* UNUSED_PARAM */ + +#if COMPILER(INTEL) && !(defined(WIN32) || defined(_WIN32)) || COMPILER(RVCT) +template<typename T> +inline void unusedParam(T& x) { (void)x; } +#define UNUSED_PARAM(variable) unusedParam(variable) +#elif COMPILER(MSVC) +#define UNUSED_PARAM(variable) (void)&variable +#else +#define UNUSED_PARAM(variable) (void)variable +#endif + +/* UNUSED_LABEL */ + +/* This is to keep the compiler from complaining when for local labels are + declared but not referenced. For example, this can happen with code that + works with auto-generated code. + */ +#if COMPILER(MSVC) +#define UNUSED_LABEL(label) if (false) goto label +#else +#define UNUSED_LABEL(label) UNUSED_PARAM(&& label) #endif + + #endif /* WTF_Compiler_h */ diff --git a/Source/WTF/wtf/CryptographicallyRandomNumber.cpp b/Source/WTF/wtf/CryptographicallyRandomNumber.cpp index e896d6f59..a0aecfe99 100644 --- a/Source/WTF/wtf/CryptographicallyRandomNumber.cpp +++ b/Source/WTF/wtf/CryptographicallyRandomNumber.cpp @@ -30,14 +30,12 @@ #include "config.h" #include "CryptographicallyRandomNumber.h" +#include "NeverDestroyed.h" #include "OSRandomSource.h" -#include "StdLibExtras.h" #include "ThreadingPrimitives.h" namespace WTF { -#if USE(OS_RANDOMNESS) - namespace { class ARC4Stream { @@ -160,7 +158,8 @@ void ARC4RandomNumberGenerator::randomValues(void* buffer, size_t length) ARC4RandomNumberGenerator& sharedRandomNumberGenerator() { - DEFINE_STATIC_LOCAL(ARC4RandomNumberGenerator, randomNumberGenerator, ()); + static NeverDestroyed<ARC4RandomNumberGenerator> randomNumberGenerator; + return randomNumberGenerator; } @@ -176,6 +175,4 @@ void cryptographicallyRandomValues(void* buffer, size_t length) sharedRandomNumberGenerator().randomValues(buffer, length); } -#endif - } diff --git a/Source/WTF/wtf/CryptographicallyRandomNumber.h b/Source/WTF/wtf/CryptographicallyRandomNumber.h index 2262b6c3b..6e8f8756e 100644 --- a/Source/WTF/wtf/CryptographicallyRandomNumber.h +++ b/Source/WTF/wtf/CryptographicallyRandomNumber.h @@ -30,16 +30,12 @@ namespace WTF { -#if USE(OS_RANDOMNESS) WTF_EXPORT_PRIVATE uint32_t cryptographicallyRandomNumber(); WTF_EXPORT_PRIVATE void cryptographicallyRandomValues(void* buffer, size_t length); -#endif } -#if USE(OS_RANDOMNESS) using WTF::cryptographicallyRandomNumber; using WTF::cryptographicallyRandomValues; -#endif #endif diff --git a/Source/WTF/wtf/CurrentTime.cpp b/Source/WTF/wtf/CurrentTime.cpp index 8d16a4e3f..627d25573 100644 --- a/Source/WTF/wtf/CurrentTime.cpp +++ b/Source/WTF/wtf/CurrentTime.cpp @@ -1,7 +1,8 @@ /* - * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Google Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,7 +34,8 @@ #include "config.h" #include "CurrentTime.h" -#if PLATFORM(MAC) +#if OS(DARWIN) +#include <mach/mach.h> #include <mach/mach_time.h> #include <sys/time.h> #elif OS(WINDOWS) @@ -47,15 +49,13 @@ #include <stdint.h> #include <time.h> -#elif PLATFORM(WX) -#include <wx/datetime.h> #elif PLATFORM(EFL) #include <Ecore.h> #else #include <sys/time.h> #endif -#if PLATFORM(GTK) +#if USE(GLIB) && !PLATFORM(EFL) #include <glib.h> #endif @@ -65,8 +65,6 @@ namespace WTF { -#if !PLATFORM(CHROMIUM) - #if OS(WINDOWS) // Number of 100 nanosecond between January 1, 1601 and January 1, 1970. @@ -224,7 +222,7 @@ double currentTime() #endif // USE(QUERY_PERFORMANCE_COUNTER) -#elif PLATFORM(GTK) +#elif USE(GLIB) && !PLATFORM(EFL) // Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides // better accuracy compared with Windows implementation of g_get_current_time: @@ -237,14 +235,6 @@ double currentTime() return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0); } -#elif PLATFORM(WX) - -double currentTime() -{ - wxDateTime now = wxDateTime::UNow(); - return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0); -} - #elif PLATFORM(EFL) double currentTime() @@ -293,7 +283,7 @@ double monotonicallyIncreasingTime() return ecore_time_get(); } -#elif PLATFORM(GTK) +#elif USE(GLIB) && !PLATFORM(EFL) && !PLATFORM(QT) double monotonicallyIncreasingTime() { @@ -333,6 +323,51 @@ double monotonicallyIncreasingTime() #endif -#endif // !PLATFORM(CHROMIUM) +double currentCPUTime() +{ +#if OS(DARWIN) + mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT; + thread_basic_info_data_t info; + + // Get thread information + mach_port_t threadPort = mach_thread_self(); + thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount); + mach_port_deallocate(mach_task_self(), threadPort); + + double time = info.user_time.seconds + info.user_time.microseconds / 1000000.; + time += info.system_time.seconds + info.system_time.microseconds / 1000000.; + + return time; +#elif OS(WINDOWS) + union { + FILETIME fileTime; + unsigned long long fileTimeAsLong; + } userTime, kernelTime; + + // GetThreadTimes won't accept null arguments so we pass these even though + // they're not used. + FILETIME creationTime, exitTime; + + GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime); + + return userTime.fileTimeAsLong / 10000000. + kernelTime.fileTimeAsLong / 10000000.; +#elif OS(QNX) + struct timespec time; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time)) + CRASH(); + return time.tv_sec + time.tv_nsec / 1.0e9; +#else + // FIXME: We should return the time the current thread has spent executing. + + // use a relative time from first call in order to avoid an overflow + static double firstTime = currentTime(); + return currentTime() - firstTime; +#endif +} + +double currentCPUTimeMS() +{ + return currentCPUTime() * 1000; +} } // namespace WTF diff --git a/Source/WTF/wtf/CurrentTime.h b/Source/WTF/wtf/CurrentTime.h index e93873117..2a60eda77 100644 --- a/Source/WTF/wtf/CurrentTime.h +++ b/Source/WTF/wtf/CurrentTime.h @@ -51,10 +51,19 @@ inline double currentTimeMS() // On unsupported platforms, this function only guarantees the result will be non-decreasing. WTF_EXPORT_PRIVATE double monotonicallyIncreasingTime(); +// Returns the current CPU time of the current thread in seconds. +// Precision varies depending on platform but is usually as good or better +// than a millisecond. +WTF_EXPORT_PRIVATE double currentCPUTime(); + +// Returns the current CPU time of the current thread in milliseconds. +WTF_EXPORT_PRIVATE double currentCPUTimeMS(); + } // namespace WTF using WTF::currentTime; using WTF::currentTimeMS; using WTF::monotonicallyIncreasingTime; +using WTF::currentCPUTime; #endif // CurrentTime_h diff --git a/Source/WTF/wtf/DataLog.cpp b/Source/WTF/wtf/DataLog.cpp index d9d0e5fb9..d0d5a5741 100644 --- a/Source/WTF/wtf/DataLog.cpp +++ b/Source/WTF/wtf/DataLog.cpp @@ -73,10 +73,8 @@ static void initializeLogFileOnce() #endif if (filename) { - FILE* rawFile = fopen(actualFilename, "w"); - if (rawFile) - file = new FilePrintStream(rawFile); - else + file = FilePrintStream::open(actualFilename, "w").leakPtr(); + if (!file) fprintf(stderr, "Warning: Could not open log file %s for writing.\n", actualFilename); } #endif // DATA_LOG_TO_FILE diff --git a/Source/WTF/wtf/DataLog.h b/Source/WTF/wtf/DataLog.h index f434b71d3..0bd8efe72 100644 --- a/Source/WTF/wtf/DataLog.h +++ b/Source/WTF/wtf/DataLog.h @@ -100,6 +100,24 @@ void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& val dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10); } +template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11> +void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11) +{ + dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11); +} + +template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12> +void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12) +{ + dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12); +} + +template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13> +void dataLog(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13) +{ + dataFile().print(value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12, value13); +} + } // namespace WTF using WTF::dataLog; diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp index 6d0e5d73f..65be223bb 100644 --- a/Source/WTF/wtf/DateMath.cpp +++ b/Source/WTF/wtf/DateMath.cpp @@ -135,7 +135,7 @@ static const int firstDayOfMonth[2][12] = { #if !OS(WINCE) static inline void getLocalTime(const time_t* localTime, struct tm* localTM) { -#if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) +#if COMPILER(MINGW) *localTM = *localtime(localTime); #elif COMPILER(MSVC) localtime_s(localTM, localTime); @@ -374,7 +374,9 @@ int equivalentYearForDST(int year) return year; } -int32_t calculateUTCOffset() +#if !HAVE(TM_GMTOFF) + +static int32_t calculateUTCOffset() { #if OS(WINDOWS) TIME_ZONE_INFORMATION timeZoneInformation; @@ -418,28 +420,20 @@ int32_t calculateUTCOffset() /* * Get the DST offset for the time passed in. */ -static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset) +static double calculateDSTOffset(time_t localTime, double utcOffset) { #if OS(WINCE) - UNUSED_PARAM(localTimeSeconds); + UNUSED_PARAM(localTime); UNUSED_PARAM(utcOffset); return 0; #else - if (localTimeSeconds > maxUnixTime) - localTimeSeconds = maxUnixTime; - else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) - localTimeSeconds += secondsPerDay; - //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset() - double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; + double offsetTime = (localTime * msPerSecond) + utcOffset; // Offset from UTC but doesn't include DST obviously int offsetHour = msToHours(offsetTime); int offsetMinute = msToMinutes(offsetTime); - // FIXME: time_t has a potential problem in 2038 - time_t localTime = static_cast<time_t>(localTimeSeconds); - tm localTM; getLocalTime(&localTime, &localTM); @@ -452,10 +446,12 @@ static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset #endif } -// Get the DST offset, given a time in UTC -double calculateDSTOffset(double ms, double utcOffset) +#endif + +// Returns combined offset in millisecond (UTC + DST). +LocalTimeOffset calculateLocalTimeOffset(double ms) { - // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate + // On Mac OS X, the call to localtime (see calculateDSTOffset) will return historically accurate // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript // standard explicitly dictates that historical information should not be considered when // determining DST. For this reason we shift away from years that localtime can handle but would @@ -471,7 +467,23 @@ double calculateDSTOffset(double ms, double utcOffset) ms = (day * msPerDay) + msToMilliseconds(ms); } - return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset); + double localTimeSeconds = ms / msPerSecond; + if (localTimeSeconds > maxUnixTime) + localTimeSeconds = maxUnixTime; + else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0). + localTimeSeconds += secondsPerDay; + // FIXME: time_t has a potential problem in 2038. + time_t localTime = static_cast<time_t>(localTimeSeconds); + +#if HAVE(TM_GMTOFF) + tm localTM; + getLocalTime(&localTime, &localTM); + return LocalTimeOffset(localTM.tm_isdst, localTM.tm_gmtoff * msPerSecond); +#else + double utcOffset = calculateUTCOffset(); + double dstOffset = calculateDSTOffset(localTime, utcOffset); + return LocalTimeOffset(dstOffset, utcOffset + dstOffset); +#endif } void initializeDates() @@ -485,7 +497,7 @@ void initializeDates() equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. } -static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, double second) +static inline double ymdhmsToSeconds(int year, long mon, long day, long hour, long minute, double second) { double days = (day - 32075) + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4) @@ -554,11 +566,21 @@ static int findMonth(const char* monthStr) return -1; } +static bool parseInt(const char* string, char** stopPosition, int base, int* result) +{ + long longResult = strtol(string, stopPosition, base); + // Avoid the use of errno as it is not available on Windows CE + if (string == *stopPosition || longResult <= std::numeric_limits<int>::min() || longResult >= std::numeric_limits<int>::max()) + return false; + *result = static_cast<int>(longResult); + return true; +} + static bool parseLong(const char* string, char** stopPosition, int base, long* result) { *result = strtol(string, stopPosition, base); // Avoid the use of errno as it is not available on Windows CE - if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX) + if (string == *stopPosition || *result == std::numeric_limits<long>::min() || *result == std::numeric_limits<long>::max()) return false; return true; } @@ -566,14 +588,14 @@ static bool parseLong(const char* string, char** stopPosition, int base, long* r // Parses a date with the format YYYY[-MM[-DD]]. // Year parsing is lenient, allows any number of digits, and +/-. // Returns 0 if a parse error occurs, else returns the end of the parsed portion of the string. -static char* parseES5DatePortion(const char* currentPosition, long& year, long& month, long& day) +static char* parseES5DatePortion(const char* currentPosition, int& year, long& month, long& day) { char* postParsePosition; // This is a bit more lenient on the year string than ES5 specifies: // instead of restricting to 4 digits (or 6 digits with mandatory +/-), // it accepts any integer value. Consider this an implementation fallback. - if (!parseLong(currentPosition, &postParsePosition, 10, &year)) + if (!parseInt(currentPosition, &postParsePosition, 10, &year)) return 0; // Check for presence of -MM portion. @@ -710,7 +732,7 @@ double parseES5DateFromNullTerminatedCharacters(const char* dateString) static const long daysPerMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // The year must be present, but the other fields may be omitted - see ES5.1 15.9.1.15. - long year = 0; + int year = 0; long month = 1; long day = 1; long hours = 0; @@ -816,7 +838,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT if (day < 0) return std::numeric_limits<double>::quiet_NaN(); - long year = 0; + int year = 0; if (day > 31) { // ### where is the boundary and what happens below? if (*dateString != '/') @@ -824,7 +846,9 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT // looks like a YYYY/MM/DD date if (!*++dateString) return std::numeric_limits<double>::quiet_NaN(); - year = day; + if (day <= std::numeric_limits<int>::min() || day >= std::numeric_limits<int>::max()) + return std::numeric_limits<double>::quiet_NaN(); + year = static_cast<int>(day); if (!parseLong(dateString, &newPosStr, 10, &month)) return std::numeric_limits<double>::quiet_NaN(); month -= 1; @@ -879,7 +903,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT // '99 23:12:40 GMT' if (year <= 0 && *dateString) { - if (!parseLong(dateString, &newPosStr, 10, &year)) + if (!parseInt(dateString, &newPosStr, 10, &year)) return std::numeric_limits<double>::quiet_NaN(); } @@ -966,7 +990,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT // The year may be after the time but before the time zone. if (isASCIIDigit(*dateString) && year == -1) { - if (!parseLong(dateString, &newPosStr, 10, &year)) + if (!parseInt(dateString, &newPosStr, 10, &year)) return std::numeric_limits<double>::quiet_NaN(); dateString = newPosStr; skipSpacesAndComments(dateString); @@ -981,8 +1005,8 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT } if (*dateString == '+' || *dateString == '-') { - long o; - if (!parseLong(dateString, &newPosStr, 10, &o)) + int o; + if (!parseInt(dateString, &newPosStr, 10, &o)) return std::numeric_limits<double>::quiet_NaN(); dateString = newPosStr; @@ -990,7 +1014,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT return std::numeric_limits<double>::quiet_NaN(); int sgn = (o < 0) ? -1 : 1; - o = labs(o); + o = abs(o); if (*dateString != ':') { if (o >= 24) offset = ((o / 100) * 60 + (o % 100)) * sgn; @@ -998,8 +1022,8 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT offset = o * 60 * sgn; } else { // GMT+05:00 ++dateString; // skip the ':' - long o2; - if (!parseLong(dateString, &newPosStr, 10, &o2)) + int o2; + if (!parseInt(dateString, &newPosStr, 10, &o2)) return std::numeric_limits<double>::quiet_NaN(); dateString = newPosStr; offset = (o * 60 + o2) * sgn; @@ -1020,7 +1044,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveT skipSpacesAndComments(dateString); if (*dateString && year == -1) { - if (!parseLong(dateString, &newPosStr, 10, &year)) + if (!parseInt(dateString, &newPosStr, 10, &year)) return std::numeric_limits<double>::quiet_NaN(); dateString = newPosStr; skipSpacesAndComments(dateString); @@ -1046,21 +1070,19 @@ double parseDateFromNullTerminatedCharacters(const char* dateString) bool haveTZ; int offset; double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); - if (isnan(ms)) + if (std::isnan(ms)) return std::numeric_limits<double>::quiet_NaN(); // fall back to local timezone - if (!haveTZ) { - double utcOffset = calculateUTCOffset(); - double dstOffset = calculateDSTOffset(ms, utcOffset); - offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); - } + if (!haveTZ) + offset = calculateLocalTimeOffset(ms).offset / msPerMinute; + return ms - (offset * msPerMinute); } double timeClip(double t) { - if (!isfinite(t)) + if (!std::isfinite(t)) return std::numeric_limits<double>::quiet_NaN(); if (fabs(t) > maxECMAScriptTime) return std::numeric_limits<double>::quiet_NaN(); diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h index 8b8e282c1..cef8b09b2 100644 --- a/Source/WTF/wtf/DateMath.h +++ b/Source/WTF/wtf/DateMath.h @@ -52,18 +52,44 @@ #include <wtf/OwnArrayPtr.h> #include <wtf/PassOwnArrayPtr.h> #include <wtf/text/WTFString.h> -#include <wtf/UnusedParam.h> namespace WTF { +struct LocalTimeOffset { + LocalTimeOffset() + : isDST(false) + , offset(0) + { + } + + LocalTimeOffset(bool isDST, int offset) + : isDST(isDST) + , offset(offset) + { + } + + bool operator==(const LocalTimeOffset& other) + { + return isDST == other.isDST && offset == other.offset; + } + + bool operator!=(const LocalTimeOffset& other) + { + return isDST != other.isDST || offset != other.offset; + } + + bool isDST; + int offset; +}; + void initializeDates(); int equivalentYearForDST(int year); // Not really math related, but this is currently the only shared place to put these. -double parseES5DateFromNullTerminatedCharacters(const char* dateString); +WTF_EXPORT_PRIVATE double parseES5DateFromNullTerminatedCharacters(const char* dateString); WTF_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(const char* dateString); -double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset); -double timeClip(double); +WTF_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset); +WTF_EXPORT_PRIVATE double timeClip(double); // dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011, hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720]. String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset); @@ -87,22 +113,21 @@ const double msPerHour = 60.0 * 60.0 * 1000.0; const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; const double msPerMonth = 2592000000.0; -bool isLeapYear(int year); +WTF_EXPORT_PRIVATE bool isLeapYear(int year); // Returns the number of days from 1970-01-01 to the specified date. WTF_EXPORT_PRIVATE double dateToDaysFrom1970(int year, int month, int day); WTF_EXPORT_PRIVATE int msToYear(double ms); -double msToDays(double ms); -int msToMinutes(double ms); -int msToHours(double ms); -int dayInYear(int year, int month, int day); +WTF_EXPORT_PRIVATE double msToDays(double ms); +WTF_EXPORT_PRIVATE int msToMinutes(double ms); +WTF_EXPORT_PRIVATE int msToHours(double ms); +WTF_EXPORT_PRIVATE int dayInYear(int year, int month, int day); WTF_EXPORT_PRIVATE int dayInYear(double ms, int year); WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear); WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear); -// Returns offset milliseconds for UTC and DST. -WTF_EXPORT_PRIVATE int32_t calculateUTCOffset(); -WTF_EXPORT_PRIVATE double calculateDSTOffset(double ms, double utcOffset); +// Returns combined offset in millisecond (UTC + DST). +WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds); } // namespace WTF @@ -123,7 +148,7 @@ using WTF::msToHours; using WTF::secondsPerMinute; using WTF::parseDateFromNullTerminatedCharacters; using WTF::makeRFC2822DateString; -using WTF::calculateUTCOffset; -using WTF::calculateDSTOffset; +using WTF::LocalTimeOffset; +using WTF::calculateLocalTimeOffset; #endif // DateMath_h diff --git a/Source/WTF/wtf/DecimalNumber.h b/Source/WTF/wtf/DecimalNumber.h index 8278dfe4f..181911079 100644 --- a/Source/WTF/wtf/DecimalNumber.h +++ b/Source/WTF/wtf/DecimalNumber.h @@ -40,7 +40,7 @@ class DecimalNumber { public: DecimalNumber(double d) { - ASSERT(isfinite(d)); + ASSERT(std::isfinite(d)); dtoa(m_significand, d, m_sign, m_exponent, m_precision); ASSERT(m_precision); @@ -54,10 +54,10 @@ public: DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures) { - ASSERT(isfinite(d)); + ASSERT(std::isfinite(d)); dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision); - ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); + ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer)); while (m_precision < significantFigures) m_significand[m_precision++] = '0'; @@ -68,11 +68,11 @@ public: DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces) { - ASSERT(isfinite(d)); + ASSERT(std::isfinite(d)); dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision); unsigned significantFigures = 1 + m_exponent + decimalPlaces; - ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); + ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer)); while (m_precision < significantFigures) m_significand[m_precision++] = '0'; diff --git a/Source/WTF/wtf/Deque.h b/Source/WTF/wtf/Deque.h index e5c47b63e..5350c7ac9 100644 --- a/Source/WTF/wtf/Deque.h +++ b/Source/WTF/wtf/Deque.h @@ -79,10 +79,12 @@ namespace WTF { T& last() { ASSERT(m_start != m_end); return *(--end()); } const T& last() const { ASSERT(m_start != m_end); return *(--end()); } + PassType takeLast(); template<typename U> void append(const U&); template<typename U> void prepend(const U&); void removeFirst(); + void removeLast(); void remove(iterator&); void remove(const_iterator&); @@ -348,6 +350,7 @@ namespace WTF { destroyAll(); m_start = 0; m_end = 0; + m_buffer.deallocateBuffer(m_buffer.buffer()); checkValidity(); } @@ -383,14 +386,13 @@ namespace WTF { { checkValidity(); size_t oldCapacity = m_buffer.capacity(); - size_t newCapacity = std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1); T* oldBuffer = m_buffer.buffer(); - m_buffer.allocateBuffer(newCapacity); + m_buffer.allocateBuffer(std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1)); if (m_start <= m_end) TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start); else { TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); - size_t newStart = newCapacity - (oldCapacity - m_start); + size_t newStart = m_buffer.capacity() - (oldCapacity - m_start); TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart); m_start = newStart; } @@ -406,6 +408,14 @@ namespace WTF { return Pass::transfer(oldFirst); } + template<typename T, size_t inlineCapacity> + inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeLast() + { + T oldLast = Pass::transfer(last()); + removeLast(); + return Pass::transfer(oldLast); + } + template<typename T, size_t inlineCapacity> template<typename U> inline void Deque<T, inlineCapacity>::append(const U& value) { @@ -447,6 +457,20 @@ namespace WTF { } template<typename T, size_t inlineCapacity> + inline void Deque<T, inlineCapacity>::removeLast() + { + checkValidity(); + invalidateIterators(); + ASSERT(!isEmpty()); + if (!m_end) + m_end = m_buffer.capacity() - 1; + else + --m_end; + TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]); + checkValidity(); + } + + template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::remove(iterator& it) { it.checkValidity(); diff --git a/Source/WTF/wtf/DisallowCType.h b/Source/WTF/wtf/DisallowCType.h index a961f1d0e..c3cc07829 100644 --- a/Source/WTF/wtf/DisallowCType.h +++ b/Source/WTF/wtf/DisallowCType.h @@ -41,7 +41,7 @@ // or <glib/gi18n-lib.h>, which in turn include <xlocale/_ctype.h> which uses // isacii(). #include <wtf/Platform.h> -#if !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM) && !(OS(DARWIN) && PLATFORM(GTK)) && !OS(QNX) && !defined(_LIBCPP_VERSION) +#if !PLATFORM(QT) && !(OS(DARWIN) && PLATFORM(GTK)) && !OS(QNX) && !defined(_LIBCPP_VERSION) #include <ctype.h> diff --git a/Source/WTF/wtf/EnumClass.h b/Source/WTF/wtf/EnumClass.h new file mode 100644 index 000000000..a5729b3b9 --- /dev/null +++ b/Source/WTF/wtf/EnumClass.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2013 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 WTF_EnumClass_h +#define WTF_EnumClass_h + +#include <wtf/Compiler.h> + +namespace WTF { + +// How to define a type safe enum list using the ENUM_CLASS macros? +// =============================================================== +// To get an enum list like this: +// +// enum class MyEnums { +// Value1, +// Value2, +// ... +// ValueN +// }; +// +// ... write this: +// +// ENUM_CLASS(MyEnums) { +// Value1, +// Value2, +// ... +// ValueN +// } ENUM_CLASS_END(MyEnums); +// +// The ENUM_CLASS macros will use C++11's enum class if the compiler supports it. +// Otherwise, it will use the EnumClass template below. + +#if COMPILER_SUPPORTS(CXX_STRONG_ENUMS) + +#define ENUM_CLASS(__enumName) \ + enum class __enumName + +#define ENUM_CLASS_END(__enumName) + +#else // !COMPILER_SUPPORTS(CXX_STRONG_ENUMS) + +// How to define a type safe enum list using the EnumClass template? +// ================================================================ +// Definition should be a struct that encapsulates an enum list. +// The enum list should be names Enums. +// +// Here's an example of how to define a type safe enum named MyEnum using +// the EnumClass template: +// +// struct MyEnumDefinition { +// enum Enums { +// ValueDefault, +// Value1, +// ... +// ValueN +// }; +// }; +// typedef EnumClass<MyEnumDefinition, MyEnumDefinition::ValueDefault> MyEnum; +// +// With that, you can now use MyEnum enum values as follow: +// +// MyEnum value1; // value1 is assigned MyEnum::ValueDefault by default. +// MyEnum value2 = MyEnum::Value1; // value2 is assigned MyEnum::Value1; + +template <typename Definition> +class EnumClass : public Definition { + typedef enum Definition::Enums Value; +public: + ALWAYS_INLINE EnumClass() { } + ALWAYS_INLINE EnumClass(Value value) : m_value(value) { } + + ALWAYS_INLINE Value value() const { return m_value; } + + ALWAYS_INLINE bool operator==(const EnumClass other) { return m_value == other.m_value; } + ALWAYS_INLINE bool operator!=(const EnumClass other) { return m_value != other.m_value; } + ALWAYS_INLINE bool operator<(const EnumClass other) { return m_value < other.m_value; } + ALWAYS_INLINE bool operator<=(const EnumClass other) { return m_value <= other.m_value; } + ALWAYS_INLINE bool operator>(const EnumClass other) { return m_value > other.m_value; } + ALWAYS_INLINE bool operator>=(const EnumClass other) { return m_value >= other.m_value; } + + ALWAYS_INLINE bool operator==(const Value value) { return m_value == value; } + ALWAYS_INLINE bool operator!=(const Value value) { return m_value != value; } + ALWAYS_INLINE bool operator<(const Value value) { return m_value < value; } + ALWAYS_INLINE bool operator<=(const Value value) { return m_value <= value; } + ALWAYS_INLINE bool operator>(const Value value) { return m_value > value; } + ALWAYS_INLINE bool operator>=(const Value value) { return m_value >= value; } + + ALWAYS_INLINE operator Value() { return m_value; } + +private: + Value m_value; +}; + +#define ENUM_CLASS(__enumName) \ + struct __enumName ## Definition { \ + enum Enums + +#define ENUM_CLASS_END(__enumName) \ + ; \ + }; \ + typedef EnumClass< __enumName ## Definition > __enumName + +#endif // !COMPILER_SUPPORTS(CXX_STRONG_ENUMS) + +} // namespace WTF + +#if !COMPILER_SUPPORTS(CXX_STRONG_ENUMS) +using WTF::EnumClass; +#endif + +#endif // WTF_EnumClass_h diff --git a/Source/WTF/wtf/ExportMacros.h b/Source/WTF/wtf/ExportMacros.h index ef9bd23f7..920fdfe9e 100644 --- a/Source/WTF/wtf/ExportMacros.h +++ b/Source/WTF/wtf/ExportMacros.h @@ -38,7 +38,7 @@ // being local to the target being generated, and thus not subject to (e.g.) ELF // symbol interposition rules. -#if !PLATFORM(CHROMIUM) && OS(WINDOWS) +#if OS(WINDOWS) #define HAVE_INTERNAL_VISIBILITY 1 #define WTF_INTERNAL #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) @@ -48,7 +48,7 @@ #define WTF_INTERNAL #endif -#if !PLATFORM(CHROMIUM) && OS(WINDOWS) +#if OS(WINDOWS) #define WTF_EXPORT_DECLARATION __declspec(dllexport) #define WTF_IMPORT_DECLARATION __declspec(dllimport) @@ -68,7 +68,7 @@ #endif -#if defined(BUILDING_WTF) || defined(STATICALLY_LINKED_WITH_WTF) || (PLATFORM(WX) && defined(BUILDING_JavaScriptCore)) +#if defined(BUILDING_WTF) || defined(STATICALLY_LINKED_WITH_WTF) #define WTF_IS_LINKED_IN_SAME_BINARY 1 #endif @@ -89,15 +89,15 @@ #else // !USE(EXPORT_MACROS) -#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) +#if OS(WINDOWS) && !COMPILER(GCC) #if defined(BUILDING_WTF) || defined(STATICALLY_LINKED_WITH_WTF) #define WTF_EXPORTDATA __declspec(dllexport) #else #define WTF_EXPORTDATA __declspec(dllimport) #endif -#else // PLATFORM(CHROMIUM) || !OS(WINDOWS) || COMPILER(GCC) +#else // !OS(WINDOWS) || COMPILER(GCC) #define WTF_EXPORTDATA -#endif // !PLATFORM(CHROMIUM)... +#endif #define WTF_EXPORTCLASS WTF_EXPORTDATA @@ -131,21 +131,7 @@ #define WTF_EXPORT_PRIVATE WTF_IMPORT #endif -// wxWebKit uses RTTI because wx itself does, so use a special macro for -// extra exports it needs. -#if PLATFORM(WX) -#define WTF_EXPORT_PRIVATE_RTTI WTF_EXPORT_PRIVATE -#define WTF_EXPORT_PRIVATE_NO_RTTI -#else -#define WTF_EXPORT_PRIVATE_RTTI -#define WTF_EXPORT_PRIVATE_NO_RTTI WTF_EXPORT_PRIVATE -#endif - -#if PLATFORM(WIN) -#define WTF_EXPORT_STRING_API -#else #define WTF_EXPORT_STRING_API WTF_EXPORT_PRIVATE -#endif #define WTF_EXPORT_HIDDEN WTF_HIDDEN diff --git a/Source/WTF/wtf/FastBitVector.h b/Source/WTF/wtf/FastBitVector.h index 97f9adf6a..c34dcf513 100644 --- a/Source/WTF/wtf/FastBitVector.h +++ b/Source/WTF/wtf/FastBitVector.h @@ -146,13 +146,13 @@ public: void set(size_t i) { - ASSERT(i < m_numBits); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits); m_array[i >> 5] |= (1 << (i & 31)); } void clear(size_t i) { - ASSERT(i < m_numBits); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits); m_array[i >> 5] &= ~(1 << (i & 31)); } @@ -166,7 +166,7 @@ public: bool get(size_t i) const { - ASSERT(i < m_numBits); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_numBits); return !!(m_array[i >> 5] & (1 << (i & 31))); } private: diff --git a/Source/WTF/wtf/FastMalloc.cpp b/Source/WTF/wtf/FastMalloc.cpp index f2e34c7ad..82fbd25f5 100644 --- a/Source/WTF/wtf/FastMalloc.cpp +++ b/Source/WTF/wtf/FastMalloc.cpp @@ -78,6 +78,8 @@ #include "FastMalloc.h" #include "Assertions.h" +#include "CurrentTime.h" + #include <limits> #if OS(WINDOWS) #include <windows.h> @@ -86,7 +88,10 @@ #endif #include <string.h> #include <wtf/StdLibExtras.h> -#include <wtf/UnusedParam.h> + +#if OS(DARWIN) +#include <malloc/malloc.h> +#endif #ifndef NO_TCMALLOC_SAMPLES #ifdef WTF_CHANGES @@ -100,6 +105,11 @@ #define FORCE_SYSTEM_MALLOC 1 #endif +// Harden the pointers stored in the TCMalloc linked lists +#if COMPILER(GCC) && !PLATFORM(QT) +#define ENABLE_TCMALLOC_HARDENING 1 +#endif + // Use a background thread to periodically scavenge memory to release back to the system #if PLATFORM(IOS) #define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0 @@ -224,14 +234,21 @@ TryMallocReturnValue tryFastZeroedMalloc(size_t n) #if FORCE_SYSTEM_MALLOC -#if OS(DARWIN) -#include <malloc/malloc.h> -#elif OS(WINDOWS) +#if OS(WINDOWS) #include <malloc.h> #endif namespace WTF { +size_t fastMallocGoodSize(size_t bytes) +{ +#if OS(DARWIN) + return malloc_good_size(bytes); +#else + return bytes; +#endif +} + TryMallocReturnValue tryFastMalloc(size_t n) { ASSERT(!isForbidden()); @@ -407,13 +424,15 @@ extern "C" WTF_EXPORT_PRIVATE const int jscore_fastmalloc_introspection = 0; #else // FORCE_SYSTEM_MALLOC -#include "AlwaysInline.h" #include "TCPackedCache.h" #include "TCPageMap.h" #include "TCSpinLock.h" #include "TCSystemAlloc.h" +#include "ThreadSpecific.h" #include <algorithm> +#if USE(PTHREADS) #include <pthread.h> +#endif #include <stdarg.h> #include <stddef.h> #include <stdint.h> @@ -434,25 +453,24 @@ extern "C" WTF_EXPORT_PRIVATE const int jscore_fastmalloc_introspection = 0; #ifdef WTF_CHANGES #if OS(DARWIN) -#include "MallocZoneSupport.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> #endif -#if HAVE(HEADER_DETECTION_H) -#include "HeaderDetection.h" -#endif - #if HAVE(DISPATCH_H) #include <dispatch/dispatch.h> #endif -#if HAVE(PTHREAD_MACHDEP_H) +#ifdef __has_include +#if __has_include(<System/pthread_machdep.h>) + #include <System/pthread_machdep.h> #if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0) #define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1 #endif + +#endif #endif #ifndef PRIuS @@ -496,6 +514,112 @@ namespace WTF { #define MESSAGE LOG_ERROR #define CHECK_CONDITION ASSERT +static const char kLLHardeningMask = 0; +template <unsigned> struct EntropySource; +template <> struct EntropySource<4> { + static uint32_t value() + { +#if OS(DARWIN) + return arc4random(); +#else + return static_cast<uint32_t>(static_cast<uintptr_t>(currentTime() * 10000) ^ reinterpret_cast<uintptr_t>(&kLLHardeningMask)); +#endif + } +}; + +template <> struct EntropySource<8> { + static uint64_t value() + { + return EntropySource<4>::value() | (static_cast<uint64_t>(EntropySource<4>::value()) << 32); + } +}; + +#if ENABLE(TCMALLOC_HARDENING) +/* + * To make it harder to exploit use-after free style exploits + * we mask the addresses we put into our linked lists with the + * address of kLLHardeningMask. Due to ASLR the address of + * kLLHardeningMask should be sufficiently randomized to make direct + * freelist manipulation much more difficult. + */ +enum { + MaskKeyShift = 13 +}; + +static ALWAYS_INLINE uintptr_t internalEntropyValue() +{ + static uintptr_t value = EntropySource<sizeof(uintptr_t)>::value() | 1; + ASSERT(value); + return value; +} + +#define HARDENING_ENTROPY internalEntropyValue() +#define ROTATE_VALUE(value, amount) (((value) >> (amount)) | ((value) << (sizeof(value) * 8 - (amount)))) +#define XOR_MASK_PTR_WITH_KEY(ptr, key, entropy) (reinterpret_cast<__typeof__(ptr)>(reinterpret_cast<uintptr_t>(ptr)^(ROTATE_VALUE(reinterpret_cast<uintptr_t>(key), MaskKeyShift)^entropy))) + + +static ALWAYS_INLINE uint32_t freedObjectStartPoison() +{ + static uint32_t value = EntropySource<sizeof(uint32_t)>::value() | 1; + ASSERT(value); + return value; +} + +static ALWAYS_INLINE uint32_t freedObjectEndPoison() +{ + static uint32_t value = EntropySource<sizeof(uint32_t)>::value() | 1; + ASSERT(value); + return value; +} + +#define PTR_TO_UINT32(ptr) static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)) +#define END_POISON_INDEX(allocationSize) (((allocationSize) - sizeof(uint32_t)) / sizeof(uint32_t)) +#define POISON_ALLOCATION(allocation, allocationSize) do { \ + ASSERT((allocationSize) >= 2 * sizeof(uint32_t)); \ + reinterpret_cast<uint32_t*>(allocation)[0] = 0xbadbeef1; \ + reinterpret_cast<uint32_t*>(allocation)[1] = 0xbadbeef3; \ + if ((allocationSize) < 4 * sizeof(uint32_t)) \ + break; \ + reinterpret_cast<uint32_t*>(allocation)[2] = 0xbadbeef5; \ + reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] = 0xbadbeef7; \ +} while (false); + +#define POISON_DEALLOCATION_EXPLICIT(allocation, allocationSize, startPoison, endPoison) do { \ + ASSERT((allocationSize) >= 2 * sizeof(uint32_t)); \ + reinterpret_cast_ptr<uint32_t*>(allocation)[0] = 0xbadbeef9; \ + reinterpret_cast_ptr<uint32_t*>(allocation)[1] = 0xbadbeefb; \ + if ((allocationSize) < 4 * sizeof(uint32_t)) \ + break; \ + reinterpret_cast_ptr<uint32_t*>(allocation)[2] = (startPoison) ^ PTR_TO_UINT32(allocation); \ + reinterpret_cast_ptr<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] = (endPoison) ^ PTR_TO_UINT32(allocation); \ +} while (false) + +#define POISON_DEALLOCATION(allocation, allocationSize) \ + POISON_DEALLOCATION_EXPLICIT(allocation, (allocationSize), freedObjectStartPoison(), freedObjectEndPoison()) + +#define MAY_BE_POISONED(allocation, allocationSize) (((allocationSize) >= 4 * sizeof(uint32_t)) && ( \ + (reinterpret_cast<uint32_t*>(allocation)[2] == (freedObjectStartPoison() ^ PTR_TO_UINT32(allocation))) || \ + (reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] == (freedObjectEndPoison() ^ PTR_TO_UINT32(allocation))) \ +)) + +#define IS_DEFINITELY_POISONED(allocation, allocationSize) (((allocationSize) < 4 * sizeof(uint32_t)) || ( \ + (reinterpret_cast<uint32_t*>(allocation)[2] == (freedObjectStartPoison() ^ PTR_TO_UINT32(allocation))) && \ + (reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] == (freedObjectEndPoison() ^ PTR_TO_UINT32(allocation))) \ +)) + +#else + +#define POISON_ALLOCATION(allocation, allocationSize) +#define POISON_DEALLOCATION(allocation, allocationSize) +#define POISON_DEALLOCATION_EXPLICIT(allocation, allocationSize, startPoison, endPoison) +#define MAY_BE_POISONED(allocation, allocationSize) (false) +#define IS_DEFINITELY_POISONED(allocation, allocationSize) (true) +#define XOR_MASK_PTR_WITH_KEY(ptr, key, entropy) (((void)entropy), ((void)key), ptr) + +#define HARDENING_ENTROPY 0 + +#endif + //------------------------------------------------------------------- // Configuration //------------------------------------------------------------------- @@ -503,12 +627,25 @@ namespace WTF { // Not all possible combinations of the following parameters make // sense. In particular, if kMaxSize increases, you may have to // increase kNumClasses as well. -static const size_t kPageShift = 12; +#if OS(DARWIN) +# define K_PAGE_SHIFT PAGE_SHIFT +# if (K_PAGE_SHIFT == 12) +# define K_NUM_CLASSES 68 +# elif (K_PAGE_SHIFT == 14) +# define K_NUM_CLASSES 77 +# else +# error "Unsupported PAGE_SHIFT amount" +# endif +#else +# define K_PAGE_SHIFT 12 +# define K_NUM_CLASSES 68 +#endif +static const size_t kPageShift = K_PAGE_SHIFT; static const size_t kPageSize = 1 << kPageShift; -static const size_t kMaxSize = 8u * kPageSize; +static const size_t kMaxSize = 32u * 1024; static const size_t kAlignShift = 3; static const size_t kAlignment = 1 << kAlignShift; -static const size_t kNumClasses = 68; +static const size_t kNumClasses = K_NUM_CLASSES; // Allocates a big block of memory for the pagemap once we reach more than // 128MB @@ -628,12 +765,43 @@ static size_t class_to_size[kNumClasses]; // Mapping from size class to number of pages to allocate at a time static size_t class_to_pages[kNumClasses]; +// Hardened singly linked list. We make this a class to allow compiler to +// statically prevent mismatching hardened and non-hardened list +class HardenedSLL { +public: + static ALWAYS_INLINE HardenedSLL create(void* value) + { + HardenedSLL result; + result.m_value = value; + return result; + } + + static ALWAYS_INLINE HardenedSLL null() + { + HardenedSLL result; + result.m_value = 0; + return result; + } + + ALWAYS_INLINE void setValue(void* value) { m_value = value; } + ALWAYS_INLINE void* value() const { return m_value; } + ALWAYS_INLINE bool operator!() const { return !m_value; } + typedef void* (HardenedSLL::*UnspecifiedBoolType); + ALWAYS_INLINE operator UnspecifiedBoolType() const { return m_value ? &HardenedSLL::m_value : 0; } + + bool operator!=(const HardenedSLL& other) const { return m_value != other.m_value; } + bool operator==(const HardenedSLL& other) const { return m_value == other.m_value; } + +private: + void* m_value; +}; + // TransferCache is used to cache transfers of num_objects_to_move[size_class] // back and forth between thread caches and the central cache for a given size // class. struct TCEntry { - void *head; // Head of chain of objects. - void *tail; // Tail of chain of objects. + HardenedSLL head; // Head of chain of objects. + HardenedSLL tail; // Tail of chain of objects. }; // A central cache freelist can have anywhere from 0 to kNumTransferEntries // slots to put link list chains into. To keep memory usage bounded the total @@ -658,63 +826,61 @@ static inline int LgFloor(size_t n) { return log; } -// Some very basic linked list functions for dealing with using void * as -// storage. - -static inline void *SLL_Next(void *t) { - return *(reinterpret_cast<void**>(t)); +// Functions for using our simple hardened singly linked list +static ALWAYS_INLINE HardenedSLL SLL_Next(HardenedSLL t, uintptr_t entropy) { + return HardenedSLL::create(XOR_MASK_PTR_WITH_KEY(*(reinterpret_cast<void**>(t.value())), t.value(), entropy)); } -static inline void SLL_SetNext(void *t, void *n) { - *(reinterpret_cast<void**>(t)) = n; +static ALWAYS_INLINE void SLL_SetNext(HardenedSLL t, HardenedSLL n, uintptr_t entropy) { + *(reinterpret_cast<void**>(t.value())) = XOR_MASK_PTR_WITH_KEY(n.value(), t.value(), entropy); } -static inline void SLL_Push(void **list, void *element) { - SLL_SetNext(element, *list); +static ALWAYS_INLINE void SLL_Push(HardenedSLL* list, HardenedSLL element, uintptr_t entropy) { + SLL_SetNext(element, *list, entropy); *list = element; } -static inline void *SLL_Pop(void **list) { - void *result = *list; - *list = SLL_Next(*list); +static ALWAYS_INLINE HardenedSLL SLL_Pop(HardenedSLL *list, uintptr_t entropy) { + HardenedSLL result = *list; + *list = SLL_Next(*list, entropy); return result; } - // Remove N elements from a linked list to which head points. head will be // modified to point to the new head. start and end will point to the first // and last nodes of the range. Note that end will point to NULL after this // function is called. -static inline void SLL_PopRange(void **head, int N, void **start, void **end) { + +static ALWAYS_INLINE void SLL_PopRange(HardenedSLL* head, int N, HardenedSLL *start, HardenedSLL *end, uintptr_t entropy) { if (N == 0) { - *start = NULL; - *end = NULL; + *start = HardenedSLL::null(); + *end = HardenedSLL::null(); return; } - void *tmp = *head; + HardenedSLL tmp = *head; for (int i = 1; i < N; ++i) { - tmp = SLL_Next(tmp); + tmp = SLL_Next(tmp, entropy); } *start = *head; *end = tmp; - *head = SLL_Next(tmp); + *head = SLL_Next(tmp, entropy); // Unlink range from list. - SLL_SetNext(tmp, NULL); + SLL_SetNext(tmp, HardenedSLL::null(), entropy); } -static inline void SLL_PushRange(void **head, void *start, void *end) { +static ALWAYS_INLINE void SLL_PushRange(HardenedSLL *head, HardenedSLL start, HardenedSLL end, uintptr_t entropy) { if (!start) return; - SLL_SetNext(end, *head); + SLL_SetNext(end, *head, entropy); *head = start; } -static inline size_t SLL_Size(void *head) { +static ALWAYS_INLINE size_t SLL_Size(HardenedSLL head, uintptr_t entropy) { int count = 0; while (head) { count++; - head = SLL_Next(head); + head = SLL_Next(head, entropy); } return count; } @@ -893,6 +1059,10 @@ static void* MetaDataAlloc(size_t bytes) { return result; } +#if defined(WTF_CHANGES) && OS(DARWIN) +class RemoteMemoryReader; +#endif + template <class T> class PageHeapAllocator { private: @@ -908,30 +1078,32 @@ class PageHeapAllocator { size_t free_avail_; // Linked list of all regions allocated by this allocator - void* allocated_regions_; + HardenedSLL allocated_regions_; // Free list of already carved objects - void* free_list_; + HardenedSLL free_list_; // Number of allocated but unfreed objects int inuse_; + uintptr_t entropy_; public: - void Init() { + void Init(uintptr_t entropy) { ASSERT(kAlignedSize <= kAllocIncrement); inuse_ = 0; - allocated_regions_ = 0; + allocated_regions_ = HardenedSLL::null(); free_area_ = NULL; free_avail_ = 0; - free_list_ = NULL; + free_list_.setValue(NULL); + entropy_ = entropy; } T* New() { // Consult free list void* result; - if (free_list_ != NULL) { - result = free_list_; - free_list_ = *(reinterpret_cast<void**>(result)); + if (free_list_) { + result = free_list_.value(); + free_list_ = SLL_Next(free_list_, entropy_); } else { if (free_avail_ < kAlignedSize) { // Need more room @@ -939,8 +1111,9 @@ class PageHeapAllocator { if (!new_allocation) CRASH(); - *reinterpret_cast_ptr<void**>(new_allocation) = allocated_regions_; - allocated_regions_ = new_allocation; + HardenedSLL new_head = HardenedSLL::create(new_allocation); + SLL_SetNext(new_head, allocated_regions_, entropy_); + allocated_regions_ = new_head; free_area_ = new_allocation + kAlignedSize; free_avail_ = kAllocIncrement - kAlignedSize; } @@ -953,20 +1126,17 @@ class PageHeapAllocator { } void Delete(T* p) { - *(reinterpret_cast<void**>(p)) = free_list_; - free_list_ = p; + HardenedSLL new_head = HardenedSLL::create(p); + SLL_SetNext(new_head, free_list_, entropy_); + free_list_ = new_head; inuse_--; } int inuse() const { return inuse_; } #if defined(WTF_CHANGES) && OS(DARWIN) - template <class Recorder> - void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader) - { - for (void* adminAllocation = allocated_regions_; adminAllocation; adminAllocation = reader.nextEntryInLinkedList(reinterpret_cast<void**>(adminAllocation))) - recorder.recordRegion(reinterpret_cast<vm_address_t>(adminAllocation), kAllocIncrement); - } + template <typename Recorder> + void recordAdministrativeRegions(Recorder&, const RemoteMemoryReader&); #endif }; @@ -1002,13 +1172,35 @@ static size_t AllocationSize(size_t bytes) { } } +enum { + kSpanCookieBits = 10, + kSpanCookieMask = (1 << 10) - 1, + kSpanThisShift = 7 +}; + +static uint32_t spanValidationCookie; +static uint32_t spanInitializerCookie() +{ + static uint32_t value = EntropySource<sizeof(uint32_t)>::value() & kSpanCookieMask; + spanValidationCookie = value; + return value; +} + // Information kept for a span (a contiguous run of pages). struct Span { PageID start; // Starting page number Length length; // Number of pages in span - Span* next; // Used when in link list - Span* prev; // Used when in link list - void* objects; // Linked list of free objects + Span* next(uintptr_t entropy) const { return XOR_MASK_PTR_WITH_KEY(m_next, this, entropy); } + Span* remoteNext(const Span* remoteSpanPointer, uintptr_t entropy) const { return XOR_MASK_PTR_WITH_KEY(m_next, remoteSpanPointer, entropy); } + Span* prev(uintptr_t entropy) const { return XOR_MASK_PTR_WITH_KEY(m_prev, this, entropy); } + void setNext(Span* next, uintptr_t entropy) { m_next = XOR_MASK_PTR_WITH_KEY(next, this, entropy); } + void setPrev(Span* prev, uintptr_t entropy) { m_prev = XOR_MASK_PTR_WITH_KEY(prev, this, entropy); } + +private: + Span* m_next; // Used when in link list + Span* m_prev; // Used when in link list +public: + HardenedSLL objects; // Linked list of free objects unsigned int free : 1; // Is the span free #ifndef NO_TCMALLOC_SAMPLES unsigned int sample : 1; // Sampled object? @@ -1016,6 +1208,17 @@ struct Span { unsigned int sizeclass : 8; // Size-class for small objects (or 0) unsigned int refcount : 11; // Number of non-free objects bool decommitted : 1; + void initCookie() + { + m_cookie = ((reinterpret_cast<uintptr_t>(this) >> kSpanThisShift) & kSpanCookieMask) ^ spanInitializerCookie(); + } + void clearCookie() { m_cookie = 0; } + bool isValid() const + { + return (((reinterpret_cast<uintptr_t>(this) >> kSpanThisShift) & kSpanCookieMask) ^ m_cookie) == spanValidationCookie; + } +private: + uint32_t m_cookie : kSpanCookieBits; #undef SPAN_HISTORY #ifdef SPAN_HISTORY @@ -1046,6 +1249,7 @@ static Span* NewSpan(PageID p, Length len) { memset(result, 0, sizeof(*result)); result->start = p; result->length = len; + result->initCookie(); #ifdef SPAN_HISTORY result->nexthistory = 0; #endif @@ -1053,10 +1257,12 @@ static Span* NewSpan(PageID p, Length len) { } static inline void DeleteSpan(Span* span) { + RELEASE_ASSERT(span->isValid()); #ifndef NDEBUG // In debug mode, trash the contents of deleted Spans memset(span, 0x3f, sizeof(*span)); #endif + span->clearCookie(); span_allocator.Delete(span); } @@ -1064,25 +1270,25 @@ static inline void DeleteSpan(Span* span) { // Doubly linked list of spans. // ------------------------------------------------------------------------- -static inline void DLL_Init(Span* list) { - list->next = list; - list->prev = list; +static inline void DLL_Init(Span* list, uintptr_t entropy) { + list->setNext(list, entropy); + list->setPrev(list, entropy); } -static inline void DLL_Remove(Span* span) { - span->prev->next = span->next; - span->next->prev = span->prev; - span->prev = NULL; - span->next = NULL; +static inline void DLL_Remove(Span* span, uintptr_t entropy) { + span->prev(entropy)->setNext(span->next(entropy), entropy); + span->next(entropy)->setPrev(span->prev(entropy), entropy); + span->setPrev(NULL, entropy); + span->setNext(NULL, entropy); } -static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) { - return list->next == list; +static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list, uintptr_t entropy) { + return list->next(entropy) == list; } -static int DLL_Length(const Span* list) { +static int DLL_Length(const Span* list, uintptr_t entropy) { int result = 0; - for (Span* s = list->next; s != list; s = s->next) { + for (Span* s = list->next(entropy); s != list; s = s->next(entropy)) { result++; } return result; @@ -1098,13 +1304,11 @@ static void DLL_Print(const char* label, const Span* list) { } #endif -static inline void DLL_Prepend(Span* list, Span* span) { - ASSERT(span->next == NULL); - ASSERT(span->prev == NULL); - span->next = list->next; - span->prev = list; - list->next->prev = span; - list->next = span; +static inline void DLL_Prepend(Span* list, Span* span, uintptr_t entropy) { + span->setNext(list->next(entropy), entropy); + span->setPrev(list, entropy); + list->next(entropy)->setPrev(span, entropy); + list->setNext(span, entropy); } //------------------------------------------------------------------- @@ -1113,16 +1317,16 @@ static inline void DLL_Prepend(Span* list, Span* span) { class TCMalloc_Central_FreeList { public: - void Init(size_t cl); + void Init(size_t cl, uintptr_t entropy); // These methods all do internal locking. // Insert the specified range into the central freelist. N is the number of // elements in the range. - void InsertRange(void *start, void *end, int N); + void InsertRange(HardenedSLL start, HardenedSLL end, int N); // Returns the actual number of fetched elements into N. - void RemoveRange(void **start, void **end, int *N); + void RemoveRange(HardenedSLL* start, HardenedSLL* end, int *N); // Returns the number of free objects in cache. size_t length() { @@ -1140,43 +1344,55 @@ class TCMalloc_Central_FreeList { template <class Finder, class Reader> void enumerateFreeObjects(Finder& finder, const Reader& reader, TCMalloc_Central_FreeList* remoteCentralFreeList) { - for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0)) - ASSERT(!span->objects); + { + static const ptrdiff_t emptyOffset = reinterpret_cast<const char*>(&empty_) - reinterpret_cast<const char*>(this); + Span* remoteEmpty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + emptyOffset); + Span* remoteSpan = nonempty_.remoteNext(remoteEmpty, entropy_); + for (Span* span = reader(remoteEmpty); span && span != &empty_; remoteSpan = span->remoteNext(remoteSpan, entropy_), span = (remoteSpan ? reader(remoteSpan) : 0)) + ASSERT(!span->objects); + } ASSERT(!nonempty_.objects); static const ptrdiff_t nonemptyOffset = reinterpret_cast<const char*>(&nonempty_) - reinterpret_cast<const char*>(this); Span* remoteNonempty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + nonemptyOffset); - Span* remoteSpan = nonempty_.next; + Span* remoteSpan = nonempty_.remoteNext(remoteNonempty, entropy_); + + for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->remoteNext(remoteSpan, entropy_), span = (remoteSpan ? reader(remoteSpan) : 0)) { + for (HardenedSLL nextObject = span->objects; nextObject; nextObject.setValue(reader.nextEntryInHardenedLinkedList(reinterpret_cast<void**>(nextObject.value()), entropy_))) { + finder.visit(nextObject.value()); + } + } - for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->next, span = (span->next ? reader(span->next) : 0)) { - for (void* nextObject = span->objects; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - finder.visit(nextObject); + for (int slot = 0; slot < used_slots_; ++slot) { + for (HardenedSLL entry = tc_slots_[slot].head; entry; entry.setValue(reader.nextEntryInHardenedLinkedList(reinterpret_cast<void**>(entry.value()), entropy_))) + finder.visit(entry.value()); } } #endif + uintptr_t entropy() const { return entropy_; } private: // REQUIRES: lock_ is held // Remove object from cache and return. // Return NULL if no free entries in cache. - void* FetchFromSpans(); + HardenedSLL FetchFromSpans(); // REQUIRES: lock_ is held // Remove object from cache and return. Fetches // from pageheap if cache is empty. Only returns // NULL on allocation failure. - void* FetchFromSpansSafe(); + HardenedSLL FetchFromSpansSafe(); // REQUIRES: lock_ is held // Release a linked list of objects to spans. // May temporarily release lock_. - void ReleaseListToSpans(void *start); + void ReleaseListToSpans(HardenedSLL start); // REQUIRES: lock_ is held // Release an object to spans. // May temporarily release lock_. - ALWAYS_INLINE void ReleaseToSpans(void* object); + ALWAYS_INLINE void ReleaseToSpans(HardenedSLL object); // REQUIRES: lock_ is held // Populate cache by fetching from the page heap. @@ -1227,6 +1443,7 @@ class TCMalloc_Central_FreeList { // adaptive value that is increased if there is lots of traffic // on a given size class. int32_t cache_size_; + uintptr_t entropy_; }; #if COMPILER(CLANG) && defined(__has_warning) @@ -1545,6 +1762,9 @@ class TCMalloc_PageHeap { // Number of pages kept in free lists uintptr_t free_pages_; + // Used for hardening + uintptr_t entropy_; + // Bytes allocated from system uint64_t system_bytes_; @@ -1637,6 +1857,7 @@ void TCMalloc_PageHeap::init() pagemap_cache_ = PageMapCache(0); free_pages_ = 0; system_bytes_ = 0; + entropy_ = HARDENING_ENTROPY; #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY free_committed_pages_ = 0; @@ -1647,11 +1868,11 @@ void TCMalloc_PageHeap::init() // Start scavenging at kMaxPages list scavenge_index_ = kMaxPages-1; COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits); - DLL_Init(&large_.normal); - DLL_Init(&large_.returned); + DLL_Init(&large_.normal, entropy_); + DLL_Init(&large_.returned, entropy_); for (size_t i = 0; i < kMaxPages; i++) { - DLL_Init(&free_[i].normal); - DLL_Init(&free_[i].returned); + DLL_Init(&free_[i].normal, entropy_); + DLL_Init(&free_[i].returned, entropy_); } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY @@ -1667,8 +1888,9 @@ void TCMalloc_PageHeap::initializeScavenger() { m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL); m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue); - dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC); - dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC); + uint64_t scavengeDelayInNanoseconds = kScavengeDelayInSeconds * NSEC_PER_SEC; + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, scavengeDelayInNanoseconds); + dispatch_source_set_timer(m_scavengeTimer, startTime, scavengeDelayInNanoseconds, scavengeDelayInNanoseconds / 10); dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); }); m_scavengingSuspended = true; } @@ -1796,11 +2018,11 @@ void TCMalloc_PageHeap::scavenge() SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i]; // If the span size is bigger than kMinSpanListsWithSpans pages return all the spans in the list, else return all but 1 span. // Return only 50% of a spanlist at a time so spans of size 1 are not the only ones left. - size_t length = DLL_Length(&slist->normal); + size_t length = DLL_Length(&slist->normal, entropy_); size_t numSpansToReturn = (i > kMinSpanListsWithSpans) ? length : length / 2; - for (int j = 0; static_cast<size_t>(j) < numSpansToReturn && !DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount; j++) { - Span* s = slist->normal.prev; - DLL_Remove(s); + for (int j = 0; static_cast<size_t>(j) < numSpansToReturn && !DLL_IsEmpty(&slist->normal, entropy_) && free_committed_pages_ > targetPageCount; j++) { + Span* s = slist->normal.prev(entropy_); + DLL_Remove(s, entropy_); ASSERT(!s->decommitted); if (!s->decommitted) { TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), @@ -1809,7 +2031,7 @@ void TCMalloc_PageHeap::scavenge() free_committed_pages_ -= s->length; s->decommitted = true; } - DLL_Prepend(&slist->returned, s); + DLL_Prepend(&slist->returned, s, entropy_); } } @@ -1836,10 +2058,10 @@ inline Span* TCMalloc_PageHeap::New(Length n) { for (Length s = n; s < kMaxPages; s++) { Span* ll = NULL; bool released = false; - if (!DLL_IsEmpty(&free_[s].normal)) { + if (!DLL_IsEmpty(&free_[s].normal, entropy_)) { // Found normal span ll = &free_[s].normal; - } else if (!DLL_IsEmpty(&free_[s].returned)) { + } else if (!DLL_IsEmpty(&free_[s].returned, entropy_)) { // Found returned span; reallocate it ll = &free_[s].returned; released = true; @@ -1848,7 +2070,7 @@ inline Span* TCMalloc_PageHeap::New(Length n) { continue; } - Span* result = ll->next; + Span* result = ll->next(entropy_); Carve(result, n, released); #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY // The newly allocated memory is from a span that's in the normal span list (already committed). Update the @@ -1885,9 +2107,9 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) { Span *best = NULL; // Search through normal list - for (Span* span = large_.normal.next; + for (Span* span = large_.normal.next(entropy_); span != &large_.normal; - span = span->next) { + span = span->next(entropy_)) { if (span->length >= n) { if ((best == NULL) || (span->length < best->length) @@ -1899,9 +2121,9 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) { } // Search through released list in case it has a better fit - for (Span* span = large_.returned.next; + for (Span* span = large_.returned.next(entropy_); span != &large_.returned; - span = span->next) { + span = span->next(entropy_)) { if (span->length >= n) { if ((best == NULL) || (span->length < best->length) @@ -1948,7 +2170,7 @@ Span* TCMalloc_PageHeap::Split(Span* span, Length n) { inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) { ASSERT(n > 0); - DLL_Remove(span); + DLL_Remove(span, entropy_); span->free = 0; Event(span, 'A', n); @@ -1974,7 +2196,7 @@ inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) { // Place leftover span on appropriate free list SpanList* listpair = (static_cast<size_t>(extra) < kMaxPages) ? &free_[extra] : &large_; Span* dst = &listpair->normal; - DLL_Prepend(dst, leftover); + DLL_Prepend(dst, leftover, entropy_); span->length = n; pagemap_.set(span->start + n - 1, span); @@ -2024,7 +2246,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) { neighboringCommittedSpansLength += len; #endif mergeDecommittedStates(span, prev); - DLL_Remove(prev); + DLL_Remove(prev, entropy_); DeleteSpan(prev); span->start -= len; span->length += len; @@ -2041,7 +2263,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) { neighboringCommittedSpansLength += len; #endif mergeDecommittedStates(span, next); - DLL_Remove(next); + DLL_Remove(next, entropy_); DeleteSpan(next); span->length += len; pagemap_.set(span->start + span->length - 1, span); @@ -2052,14 +2274,14 @@ inline void TCMalloc_PageHeap::Delete(Span* span) { span->free = 1; if (span->decommitted) { if (span->length < kMaxPages) - DLL_Prepend(&free_[span->length].returned, span); + DLL_Prepend(&free_[span->length].returned, span, entropy_); else - DLL_Prepend(&large_.returned, span); + DLL_Prepend(&large_.returned, span, entropy_); } else { if (span->length < kMaxPages) - DLL_Prepend(&free_[span->length].normal, span); + DLL_Prepend(&free_[span->length].normal, span, entropy_); else - DLL_Prepend(&large_.normal, span); + DLL_Prepend(&large_.normal, span, entropy_); } free_pages_ += n; @@ -2100,17 +2322,18 @@ void TCMalloc_PageHeap::IncrementalScavenge(Length n) { // Find index of free list to scavenge size_t index = scavenge_index_ + 1; + uintptr_t entropy = entropy_; for (size_t i = 0; i < kMaxPages+1; i++) { if (index > kMaxPages) index = 0; SpanList* slist = (index == kMaxPages) ? &large_ : &free_[index]; - if (!DLL_IsEmpty(&slist->normal)) { + if (!DLL_IsEmpty(&slist->normal, entropy)) { // Release the last span on the normal portion of this list - Span* s = slist->normal.prev; - DLL_Remove(s); + Span* s = slist->normal.prev(entropy); + DLL_Remove(s, entropy_); TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), static_cast<size_t>(s->length << kPageShift)); s->decommitted = true; - DLL_Prepend(&slist->returned, s); + DLL_Prepend(&slist->returned, s, entropy); #if PLATFORM(IOS) scavenge_counter_ = std::max<size_t>(16UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay))); @@ -2118,7 +2341,7 @@ void TCMalloc_PageHeap::IncrementalScavenge(Length n) { scavenge_counter_ = std::max<size_t>(64UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay))); #endif - if (index == kMaxPages && !DLL_IsEmpty(&slist->normal)) + if (index == kMaxPages && !DLL_IsEmpty(&slist->normal, entropy)) scavenge_index_ = index - 1; else scavenge_index_ = index; @@ -2148,12 +2371,12 @@ void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) { size_t TCMalloc_PageHeap::ReturnedBytes() const { size_t result = 0; for (unsigned s = 0; s < kMaxPages; s++) { - const int r_length = DLL_Length(&free_[s].returned); + const int r_length = DLL_Length(&free_[s].returned, entropy_); unsigned r_pages = s * r_length; result += r_pages << kPageShift; } - for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) + for (Span* s = large_.returned.next(entropy_); s != &large_.returned; s = s->next(entropy_)) result += s->length << kPageShift; return result; } @@ -2280,8 +2503,8 @@ bool TCMalloc_PageHeap::Check() { #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY size_t totalFreeCommitted = 0; #endif - ASSERT(free_[0].normal.next == &free_[0].normal); - ASSERT(free_[0].returned.next == &free_[0].returned); + ASSERT(free_[0].normal.next(entropy_) == &free_[0].normal); + ASSERT(free_[0].returned.next(entropy_) == &free_[0].returned); #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY totalFreeCommitted = CheckList(&large_.normal, kMaxPages, 1000000000, false); #else @@ -2309,7 +2532,7 @@ size_t TCMalloc_PageHeap::CheckList(Span*, Length, Length, bool) { #else size_t TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted) { size_t freeCount = 0; - for (Span* s = list->next; s != list; s = s->next) { + for (Span* s = list->next(entropy_); s != list; s = s->next(entropy_)) { CHECK_CONDITION(s->free); CHECK_CONDITION(s->length >= min_pages); CHECK_CONDITION(s->length <= max_pages); @@ -2329,12 +2552,12 @@ void TCMalloc_PageHeap::ReleaseFreeList(Span* list, Span* returned) { size_t freePageReduction = 0; #endif - while (!DLL_IsEmpty(list)) { - Span* s = list->prev; + while (!DLL_IsEmpty(list, entropy_)) { + Span* s = list->prev(entropy_); - DLL_Remove(s); + DLL_Remove(s, entropy_); s->decommitted = true; - DLL_Prepend(returned, s); + DLL_Prepend(returned, s, entropy_); TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), static_cast<size_t>(s->length << kPageShift)); #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY @@ -2363,15 +2586,20 @@ void TCMalloc_PageHeap::ReleaseFreePages() { class TCMalloc_ThreadCache_FreeList { private: - void* list_; // Linked list of nodes + HardenedSLL list_; // Linked list of nodes uint16_t length_; // Current length uint16_t lowater_; // Low water mark for list length + uintptr_t entropy_; // Entropy source for hardening public: - void Init() { - list_ = NULL; + void Init(uintptr_t entropy) { + list_.setValue(NULL); length_ = 0; lowater_ = 0; + entropy_ = entropy; +#if ENABLE(TCMALLOC_HARDENING) + ASSERT(entropy_); +#endif } // Return current length of list @@ -2381,43 +2609,56 @@ class TCMalloc_ThreadCache_FreeList { // Is list empty? bool empty() const { - return list_ == NULL; + return !list_; } // Low-water mark management int lowwatermark() const { return lowater_; } void clear_lowwatermark() { lowater_ = length_; } - ALWAYS_INLINE void Push(void* ptr) { - SLL_Push(&list_, ptr); + ALWAYS_INLINE void Push(HardenedSLL ptr) { + SLL_Push(&list_, ptr, entropy_); length_++; } - void PushRange(int N, void *start, void *end) { - SLL_PushRange(&list_, start, end); + void PushRange(int N, HardenedSLL start, HardenedSLL end) { + SLL_PushRange(&list_, start, end, entropy_); length_ = length_ + static_cast<uint16_t>(N); } - void PopRange(int N, void **start, void **end) { - SLL_PopRange(&list_, N, start, end); + void PopRange(int N, HardenedSLL* start, HardenedSLL* end) { + SLL_PopRange(&list_, N, start, end, entropy_); ASSERT(length_ >= N); length_ = length_ - static_cast<uint16_t>(N); if (length_ < lowater_) lowater_ = length_; } ALWAYS_INLINE void* Pop() { - ASSERT(list_ != NULL); + ASSERT(list_); length_--; if (length_ < lowater_) lowater_ = length_; - return SLL_Pop(&list_); - } + return SLL_Pop(&list_, entropy_).value(); + } + + // Runs through the linked list to ensure that + // we can do that, and ensures that 'missing' + // is not present + NEVER_INLINE void Validate(HardenedSLL missing, size_t size) { + HardenedSLL node = list_; + UNUSED_PARAM(size); + while (node) { + RELEASE_ASSERT(node != missing); + RELEASE_ASSERT(IS_DEFINITELY_POISONED(node.value(), size)); + node = SLL_Next(node, entropy_); + } + } #ifdef WTF_CHANGES template <class Finder, class Reader> void enumerateFreeObjects(Finder& finder, const Reader& reader) { - for (void* nextObject = list_; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - finder.visit(nextObject); + for (HardenedSLL nextObject = list_; nextObject; nextObject.setValue(reader.nextEntryInHardenedLinkedList(reinterpret_cast<void**>(nextObject.value()), entropy_))) + finder.visit(nextObject.value()); } #endif }; @@ -2444,8 +2685,10 @@ class TCMalloc_ThreadCache { uint32_t rnd_; // Cheap random number generator size_t bytes_until_sample_; // Bytes until we sample next + uintptr_t entropy_; // Entropy value used for hardening + // Allocate a new heap. REQUIRES: pageheap_lock is held. - static inline TCMalloc_ThreadCache* NewHeap(ThreadIdentifier tid); + static inline TCMalloc_ThreadCache* NewHeap(ThreadIdentifier tid, uintptr_t entropy); // Use only as pthread thread-specific destructor function. static void DestroyThreadCache(void* ptr); @@ -2454,7 +2697,7 @@ class TCMalloc_ThreadCache { TCMalloc_ThreadCache* next_; TCMalloc_ThreadCache* prev_; - void Init(ThreadIdentifier tid); + void Init(ThreadIdentifier tid, uintptr_t entropy); void Cleanup(); // Accessors (mostly just for printing stats) @@ -2464,7 +2707,7 @@ class TCMalloc_ThreadCache { size_t Size() const { return size_; } ALWAYS_INLINE void* Allocate(size_t size); - void Deallocate(void* ptr, size_t size_class); + void Deallocate(HardenedSLL ptr, size_t size_class); ALWAYS_INLINE void FetchFromCentralCache(size_t cl, size_t allocationSize); void ReleaseToCentralCache(size_t cl, int N); @@ -2525,6 +2768,13 @@ static inline TCMalloc_PageHeap* getPageHeap() #define pageheap getPageHeap() +size_t fastMallocGoodSize(size_t bytes) +{ + if (!phinited) + TCMalloc_ThreadCache::InitModule(); + return AllocationSize(bytes); +} + #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY #if HAVE(DISPATCH_H) || OS(WINDOWS) @@ -2611,10 +2861,7 @@ static bool tsd_inited = false; #if USE(PTHREAD_GETSPECIFIC_DIRECT) static const pthread_key_t heap_key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0; #else -static pthread_key_t heap_key; -#endif -#if OS(WINDOWS) -DWORD tlsIndex = TLS_OUT_OF_INDEXES; +static ThreadSpecificKey heap_key; #endif static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap) @@ -2626,12 +2873,12 @@ static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap) CRASH(); #endif +#if OS(DARWIN) // Still do pthread_setspecific even if there's an alternate form // of thread-local storage in use, to benefit from the delete callback. pthread_setspecific(heap_key, heap); - -#if OS(WINDOWS) - TlsSetValue(tlsIndex, heap); +#else + threadSpecificSet(heap_key, heap); #endif } @@ -2655,11 +2902,15 @@ static volatile size_t per_thread_cache_size = kMaxThreadCacheSize; // Central cache implementation //------------------------------------------------------------------- -void TCMalloc_Central_FreeList::Init(size_t cl) { +void TCMalloc_Central_FreeList::Init(size_t cl, uintptr_t entropy) { lock_.Init(); size_class_ = cl; - DLL_Init(&empty_); - DLL_Init(&nonempty_); + entropy_ = entropy; +#if ENABLE(TCMALLOC_HARDENING) + ASSERT(entropy_); +#endif + DLL_Init(&empty_, entropy_); + DLL_Init(&nonempty_, entropy_); counter_ = 0; cache_size_ = 1; @@ -2667,24 +2918,24 @@ void TCMalloc_Central_FreeList::Init(size_t cl) { ASSERT(cache_size_ <= kNumTransferEntries); } -void TCMalloc_Central_FreeList::ReleaseListToSpans(void* start) { +void TCMalloc_Central_FreeList::ReleaseListToSpans(HardenedSLL start) { while (start) { - void *next = SLL_Next(start); + HardenedSLL next = SLL_Next(start, entropy_); ReleaseToSpans(start); start = next; } } -ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) { - const PageID p = reinterpret_cast<uintptr_t>(object) >> kPageShift; +ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(HardenedSLL object) { + const PageID p = reinterpret_cast<uintptr_t>(object.value()) >> kPageShift; Span* span = pageheap->GetDescriptor(p); ASSERT(span != NULL); ASSERT(span->refcount > 0); // If span is empty, move it to non-empty list - if (span->objects == NULL) { - DLL_Remove(span); - DLL_Prepend(&nonempty_, span); + if (!span->objects) { + DLL_Remove(span, entropy_); + DLL_Prepend(&nonempty_, span, entropy_); Event(span, 'N', 0); } @@ -2692,8 +2943,8 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) { if (false) { // Check that object does not occur in list unsigned got = 0; - for (void* p = span->objects; p != NULL; p = *((void**) p)) { - ASSERT(p != object); + for (HardenedSLL p = span->objects; !p; SLL_Next(p, entropy_)) { + ASSERT(p.value() != object.value()); got++; } ASSERT(got + span->refcount == @@ -2705,7 +2956,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) { if (span->refcount == 0) { Event(span, '#', 0); counter_ -= (span->length<<kPageShift) / ByteSizeForClass(span->sizeclass); - DLL_Remove(span); + DLL_Remove(span, entropy_); // Release central list lock while operating on pageheap lock_.Unlock(); @@ -2715,8 +2966,8 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) { } lock_.Lock(); } else { - *(reinterpret_cast<void**>(object)) = span->objects; - span->objects = object; + SLL_SetNext(object, span->objects, entropy_); + span->objects.setValue(object.value()); } } @@ -2790,7 +3041,7 @@ bool TCMalloc_Central_FreeList::ShrinkCache(int locked_size_class, bool force) { return true; } -void TCMalloc_Central_FreeList::InsertRange(void *start, void *end, int N) { +void TCMalloc_Central_FreeList::InsertRange(HardenedSLL start, HardenedSLL end, int N) { SpinLockHolder h(&lock_); if (N == num_objects_to_move[size_class_] && MakeCacheSpace()) { @@ -2805,7 +3056,7 @@ void TCMalloc_Central_FreeList::InsertRange(void *start, void *end, int N) { ReleaseListToSpans(start); } -void TCMalloc_Central_FreeList::RemoveRange(void **start, void **end, int *N) { +ALWAYS_INLINE void TCMalloc_Central_FreeList::RemoveRange(HardenedSLL* start, HardenedSLL* end, int *N) { int num = *N; ASSERT(num > 0); @@ -2820,21 +3071,21 @@ void TCMalloc_Central_FreeList::RemoveRange(void **start, void **end, int *N) { } // TODO: Prefetch multiple TCEntries? - void *tail = FetchFromSpansSafe(); + HardenedSLL tail = FetchFromSpansSafe(); if (!tail) { // We are completely out of memory. - *start = *end = NULL; + *start = *end = HardenedSLL::null(); *N = 0; return; } - SLL_SetNext(tail, NULL); - void *head = tail; + SLL_SetNext(tail, HardenedSLL::null(), entropy_); + HardenedSLL head = tail; int count = 1; while (count < num) { - void *t = FetchFromSpans(); + HardenedSLL t = FetchFromSpans(); if (!t) break; - SLL_Push(&head, t); + SLL_Push(&head, t, entropy_); count++; } *start = head; @@ -2843,8 +3094,8 @@ void TCMalloc_Central_FreeList::RemoveRange(void **start, void **end, int *N) { } -void* TCMalloc_Central_FreeList::FetchFromSpansSafe() { - void *t = FetchFromSpans(); +ALWAYS_INLINE HardenedSLL TCMalloc_Central_FreeList::FetchFromSpansSafe() { + HardenedSLL t = FetchFromSpans(); if (!t) { Populate(); t = FetchFromSpans(); @@ -2852,19 +3103,19 @@ void* TCMalloc_Central_FreeList::FetchFromSpansSafe() { return t; } -void* TCMalloc_Central_FreeList::FetchFromSpans() { - if (DLL_IsEmpty(&nonempty_)) return NULL; - Span* span = nonempty_.next; +HardenedSLL TCMalloc_Central_FreeList::FetchFromSpans() { + if (DLL_IsEmpty(&nonempty_, entropy_)) return HardenedSLL::null(); + Span* span = nonempty_.next(entropy_); - ASSERT(span->objects != NULL); + ASSERT(span->objects); ASSERT_SPAN_COMMITTED(span); span->refcount++; - void* result = span->objects; - span->objects = *(reinterpret_cast<void**>(result)); - if (span->objects == NULL) { + HardenedSLL result = span->objects; + span->objects = SLL_Next(result, entropy_); + if (!span->objects) { // Move to empty list - DLL_Remove(span); - DLL_Prepend(&empty_, span); + DLL_Remove(span, entropy_); + DLL_Prepend(&empty_, span, entropy_); Event(span, 'E', 0); } counter_--; @@ -2905,25 +3156,42 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() { // Split the block into pieces and add to the free-list // TODO: coloring of objects to avoid cache conflicts? - void** tail = &span->objects; - char* ptr = reinterpret_cast<char*>(span->start << kPageShift); - char* limit = ptr + (npages << kPageShift); + HardenedSLL head = HardenedSLL::null(); + char* start = reinterpret_cast<char*>(span->start << kPageShift); const size_t size = ByteSizeForClass(size_class_); + char* ptr = start + (npages << kPageShift) - ((npages << kPageShift) % size); int num = 0; - char* nptr; - while ((nptr = ptr + size) <= limit) { - *tail = ptr; - tail = reinterpret_cast_ptr<void**>(ptr); - ptr = nptr; +#if ENABLE(TCMALLOC_HARDENING) + uint32_t startPoison = freedObjectStartPoison(); + uint32_t endPoison = freedObjectEndPoison(); +#endif + + while (ptr > start) { + ptr -= size; + HardenedSLL node = HardenedSLL::create(ptr); + POISON_DEALLOCATION_EXPLICIT(ptr, size, startPoison, endPoison); + SLL_SetNext(node, head, entropy_); + head = node; num++; } - ASSERT(ptr <= limit); - *tail = NULL; + ASSERT(ptr == start); + ASSERT(ptr == head.value()); +#ifndef NDEBUG + { + HardenedSLL node = head; + while (node) { + ASSERT(IS_DEFINITELY_POISONED(node.value(), size)); + node = SLL_Next(node, entropy_); + } + } +#endif + span->objects = head; + ASSERT(span->objects.value() == head.value()); span->refcount = 0; // No sub-object in use yet // Add span to list of non-empty spans lock_.Lock(); - DLL_Prepend(&nonempty_, span); + DLL_Prepend(&nonempty_, span, entropy_); counter_ += num; } @@ -2941,14 +3209,18 @@ inline bool TCMalloc_ThreadCache::SampleAllocation(size_t k) { } } -void TCMalloc_ThreadCache::Init(ThreadIdentifier tid) { +void TCMalloc_ThreadCache::Init(ThreadIdentifier tid, uintptr_t entropy) { size_ = 0; next_ = NULL; prev_ = NULL; tid_ = tid; in_setspecific_ = false; + entropy_ = entropy; +#if ENABLE(TCMALLOC_HARDENING) + ASSERT(entropy_); +#endif for (size_t cl = 0; cl < kNumClasses; ++cl) { - list_[cl].Init(); + list_[cl].Init(entropy_); } // Initialize RNG -- run it for a bit to get to good values @@ -2978,12 +3250,22 @@ ALWAYS_INLINE void* TCMalloc_ThreadCache::Allocate(size_t size) { if (list->empty()) return NULL; } size_ -= allocationSize; - return list->Pop(); + void* result = list->Pop(); + if (!result) + return 0; + RELEASE_ASSERT(IS_DEFINITELY_POISONED(result, allocationSize)); + POISON_ALLOCATION(result, allocationSize); + return result; } -inline void TCMalloc_ThreadCache::Deallocate(void* ptr, size_t cl) { - size_ += ByteSizeForClass(cl); +inline void TCMalloc_ThreadCache::Deallocate(HardenedSLL ptr, size_t cl) { + size_t allocationSize = ByteSizeForClass(cl); + size_ += allocationSize; FreeList* list = &list_[cl]; + if (MAY_BE_POISONED(ptr.value(), allocationSize)) + list->Validate(ptr, allocationSize); + + POISON_DEALLOCATION(ptr.value(), allocationSize); list->Push(ptr); // If enough data is free, put back into central cache if (list->length() > kMaxFreeListLength) { @@ -2995,7 +3277,7 @@ inline void TCMalloc_ThreadCache::Deallocate(void* ptr, size_t cl) { // Remove some objects of class "cl" from central cache and add to thread heap ALWAYS_INLINE void TCMalloc_ThreadCache::FetchFromCentralCache(size_t cl, size_t allocationSize) { int fetch_count = num_objects_to_move[cl]; - void *start, *end; + HardenedSLL start, end; central_cache[cl].RemoveRange(&start, &end, &fetch_count); list_[cl].PushRange(fetch_count, start, end); size_ += allocationSize * fetch_count; @@ -3012,12 +3294,12 @@ inline void TCMalloc_ThreadCache::ReleaseToCentralCache(size_t cl, int N) { // TODO: Use the same format internally in the thread caches? int batch_size = num_objects_to_move[cl]; while (N > batch_size) { - void *tail, *head; + HardenedSLL tail, head; src->PopRange(batch_size, &head, &tail); central_cache[cl].InsertRange(head, tail, batch_size); N -= batch_size; } - void *tail, *head; + HardenedSLL tail, head; src->PopRange(N, &head, &tail); central_cache[cl].InsertRange(head, tail, N); } @@ -3102,18 +3384,19 @@ void TCMalloc_ThreadCache::InitModule() { // object declared below. SpinLockHolder h(&pageheap_lock); if (!phinited) { + uintptr_t entropy = HARDENING_ENTROPY; #ifdef WTF_CHANGES InitTSD(); #endif InitSizeClasses(); - threadheap_allocator.Init(); - span_allocator.Init(); + threadheap_allocator.Init(entropy); + span_allocator.Init(entropy); span_allocator.New(); // Reduce cache conflicts span_allocator.New(); // Reduce cache conflicts - stacktrace_allocator.Init(); - DLL_Init(&sampled_objects); + stacktrace_allocator.Init(entropy); + DLL_Init(&sampled_objects, entropy); for (size_t i = 0; i < kNumClasses; ++i) { - central_cache[i].Init(i); + central_cache[i].Init(i, entropy); } pageheap->init(); phinited = 1; @@ -3123,10 +3406,10 @@ void TCMalloc_ThreadCache::InitModule() { } } -inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::NewHeap(ThreadIdentifier tid) { +inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::NewHeap(ThreadIdentifier tid, uintptr_t entropy) { // Create the heap and add it to the linked list TCMalloc_ThreadCache *heap = threadheap_allocator.New(); - heap->Init(tid); + heap->Init(tid, entropy); heap->next_ = thread_heaps; heap->prev_ = NULL; if (thread_heaps != NULL) thread_heaps->prev_ = heap; @@ -3141,10 +3424,10 @@ inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetThreadHeap() { // __thread is faster, but only when the kernel supports it if (KernelSupportsTLS()) return threadlocal_heap; -#elif OS(WINDOWS) - return static_cast<TCMalloc_ThreadCache*>(TlsGetValue(tlsIndex)); -#else +#elif OS(DARWIN) return static_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key)); +#else + return static_cast<TCMalloc_ThreadCache*>(threadSpecificGet(heap_key)); #endif } @@ -3173,10 +3456,7 @@ void TCMalloc_ThreadCache::InitTSD() { #if USE(PTHREAD_GETSPECIFIC_DIRECT) pthread_key_init_np(heap_key, DestroyThreadCache); #else - pthread_key_create(&heap_key, DestroyThreadCache); -#endif -#if OS(WINDOWS) - tlsIndex = TlsAlloc(); + threadSpecificKeyCreate(&heap_key, DestroyThreadCache); #endif tsd_inited = true; @@ -3240,7 +3520,7 @@ TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() { } } - if (heap == NULL) heap = NewHeap(me); + if (heap == NULL) heap = NewHeap(me, HARDENING_ENTROPY); } // We call pthread_setspecific() outside the lock because it may @@ -3677,8 +3957,9 @@ static inline void* CheckedMallocResult(void *result) static inline void* SpanToMallocResult(Span *span) { ASSERT_SPAN_COMMITTED(span); pageheap->CacheSizeClass(span->start, 0); - return - CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift)); + void* result = reinterpret_cast<void*>(span->start << kPageShift); + POISON_ALLOCATION(result, span->length << kPageShift); + return CheckedMallocResult(result); } #ifdef WTF_CHANGES @@ -3728,25 +4009,26 @@ static ALWAYS_INLINE void do_free(void* ptr) { if (ptr == NULL) return; ASSERT(pageheap != NULL); // Should not call free() before malloc() const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; - Span* span = NULL; - size_t cl = pageheap->GetSizeClassIfCached(p); + Span* span = pageheap->GetDescriptor(p); + RELEASE_ASSERT(span->isValid()); + size_t cl = span->sizeclass; - if (cl == 0) { - span = pageheap->GetDescriptor(p); - cl = span->sizeclass; + if (cl) { + size_t byteSizeForClass = ByteSizeForClass(cl); + RELEASE_ASSERT(!((reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(span->start << kPageShift)) % byteSizeForClass)); pageheap->CacheSizeClass(p, cl); - } - if (cl != 0) { + #ifndef NO_TCMALLOC_SAMPLES ASSERT(!pageheap->GetDescriptor(p)->sample); #endif TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCacheIfPresent(); if (heap != NULL) { - heap->Deallocate(ptr, cl); + heap->Deallocate(HardenedSLL::create(ptr), cl); } else { // Delete directly into central cache - SLL_SetNext(ptr, NULL); - central_cache[cl].InsertRange(ptr, ptr, 1); + POISON_DEALLOCATION(ptr, byteSizeForClass); + SLL_SetNext(HardenedSLL::create(ptr), HardenedSLL::null(), central_cache[cl].entropy()); + central_cache[cl].InsertRange(HardenedSLL::create(ptr), HardenedSLL::create(ptr), 1); } } else { SpinLockHolder h(&pageheap_lock); @@ -3759,6 +4041,8 @@ static ALWAYS_INLINE void do_free(void* ptr) { span->objects = NULL; } #endif + RELEASE_ASSERT(reinterpret_cast<void*>(span->start << kPageShift) == ptr); + POISON_DEALLOCATION(ptr, span->length << kPageShift); pageheap->Delete(span); } } @@ -4350,17 +4634,13 @@ void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; void releaseFastMallocFreeMemory() { // Flush free pages in the current thread cache back to the page heap. - // Low watermark mechanism in Scavenge() prevents full return on the first pass. - // The second pass flushes everything. - if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) { - threadCache->Scavenge(); - threadCache->Scavenge(); - } + if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) + threadCache->Cleanup(); SpinLockHolder h(&pageheap_lock); pageheap->ReleaseFreePages(); } - + FastMallocStatistics fastMallocStatistics() { FastMallocStatistics statistics; @@ -4393,8 +4673,8 @@ size_t fastMallocSize(const void* ptr) if (!span || span->free) return 0; - for (void* free = span->objects; free != NULL; free = *((void**) free)) { - if (ptr == free) + for (HardenedSLL free = span->objects; free; free = SLL_Next(free, HARDENING_ENTROPY)) { + if (ptr == free.value()) return 0; } @@ -4406,6 +4686,51 @@ size_t fastMallocSize(const void* ptr) } #if OS(DARWIN) +class RemoteMemoryReader { + task_t m_task; + memory_reader_t* m_reader; + +public: + RemoteMemoryReader(task_t task, memory_reader_t* reader) + : m_task(task) + , m_reader(reader) + { } + + void* operator()(vm_address_t address, size_t size) const + { + void* output; + kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output)); + if (err) + output = 0; + return output; + } + + template <typename T> + T* operator()(T* address, size_t size = sizeof(T)) const + { + return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size)); + } + + template <typename T> + T* nextEntryInHardenedLinkedList(T** remoteAddress, uintptr_t entropy) const + { + T** localAddress = (*this)(remoteAddress); + if (!localAddress) + return 0; + T* hardenedNext = *localAddress; + if (!hardenedNext || hardenedNext == (void*)entropy) + return 0; + return XOR_MASK_PTR_WITH_KEY(hardenedNext, remoteAddress, entropy); + } +}; + +template <typename T> +template <typename Recorder> +void PageHeapAllocator<T>::recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader) +{ + for (HardenedSLL adminAllocation = allocated_regions_; adminAllocation; adminAllocation.setValue(reader.nextEntryInHardenedLinkedList(reinterpret_cast<void**>(adminAllocation.value()), entropy_))) + recorder.recordRegion(reinterpret_cast<vm_address_t>(adminAllocation.value()), kAllocIncrement); +} class FreeObjectFinder { const RemoteMemoryReader& m_reader; @@ -4435,12 +4760,18 @@ public: class PageMapFreeObjectFinder { const RemoteMemoryReader& m_reader; FreeObjectFinder& m_freeObjectFinder; + uintptr_t m_entropy; public: - PageMapFreeObjectFinder(const RemoteMemoryReader& reader, FreeObjectFinder& freeObjectFinder) + PageMapFreeObjectFinder(const RemoteMemoryReader& reader, FreeObjectFinder& freeObjectFinder, uintptr_t entropy) : m_reader(reader) , m_freeObjectFinder(freeObjectFinder) - { } + , m_entropy(entropy) + { +#if ENABLE(TCMALLOC_HARDENING) + ASSERT(m_entropy); +#endif + } int visit(void* ptr) const { @@ -4456,8 +4787,8 @@ public: m_freeObjectFinder.visit(ptr); } else if (span->sizeclass) { // Walk the free list of the small-object span, keeping track of each object seen - for (void* nextObject = span->objects; nextObject; nextObject = m_reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - m_freeObjectFinder.visit(nextObject); + for (HardenedSLL nextObject = span->objects; nextObject; nextObject.setValue(m_reader.nextEntryInHardenedLinkedList(reinterpret_cast<void**>(nextObject.value()), m_entropy))) + m_freeObjectFinder.visit(nextObject.value()); } return span->length; } @@ -4491,15 +4822,7 @@ public: void recordPendingRegions() { - Span* lastSpan = m_coalescedSpans[m_coalescedSpans.size() - 1]; - vm_range_t ptrRange = { m_coalescedSpans[0]->start << kPageShift, 0 }; - ptrRange.size = (lastSpan->start << kPageShift) - ptrRange.address + (lastSpan->length * kPageSize); - - // Mark the memory region the spans represent as a candidate for containing pointers - if (m_typeMask & MALLOC_PTR_REGION_RANGE_TYPE) - (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1); - - if (!(m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) { + if (!(m_typeMask & (MALLOC_PTR_IN_USE_RANGE_TYPE | MALLOC_PTR_REGION_RANGE_TYPE))) { m_coalescedSpans.clear(); return; } @@ -4529,7 +4852,7 @@ public: } } - (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, allocatedPointers.data(), allocatedPointers.size()); + (*m_recorder)(m_task, m_context, m_typeMask & (MALLOC_PTR_IN_USE_RANGE_TYPE | MALLOC_PTR_REGION_RANGE_TYPE), allocatedPointers.data(), allocatedPointers.size()); m_coalescedSpans.clear(); } @@ -4543,9 +4866,8 @@ public: if (!span || !span->start) return 1; - if (m_seenPointers.contains(ptr)) + if (!m_seenPointers.add(ptr).isNewEntry) return span->length; - m_seenPointers.add(ptr); if (!m_coalescedSpans.size()) { m_coalescedSpans.append(span); @@ -4630,7 +4952,7 @@ kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typ finder.findFreeObjects(centralCaches, kNumClasses, mzone->m_centralCaches); TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_; - PageMapFreeObjectFinder pageMapFinder(memoryReader, finder); + PageMapFreeObjectFinder pageMapFinder(memoryReader, finder, pageHeap->entropy_); pageMap->visitValues(pageMapFinder, memoryReader); PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder); @@ -4688,10 +5010,7 @@ void* FastMallocZone::zoneRealloc(malloc_zone_t*, void*, size_t) extern "C" { malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print, &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics - -#if OS(IOS) || __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher. -#endif #if OS(IOS) || __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 , 0, 0, 0, 0 // These members will not be used unless the zone advertises itself as version seven or higher. #endif diff --git a/Source/WTF/wtf/FastMalloc.h b/Source/WTF/wtf/FastMalloc.h index 1300a8ed6..e80fca863 100644 --- a/Source/WTF/wtf/FastMalloc.h +++ b/Source/WTF/wtf/FastMalloc.h @@ -35,6 +35,7 @@ namespace WTF { WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t); WTF_EXPORT_PRIVATE char* fastStrDup(const char*); WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*); + WTF_EXPORT_PRIVATE size_t fastMallocGoodSize(size_t); struct TryMallocReturnValue { TryMallocReturnValue(void* data) @@ -223,6 +224,7 @@ namespace WTF { using WTF::fastCalloc; using WTF::fastFree; using WTF::fastMalloc; +using WTF::fastMallocGoodSize; using WTF::fastMallocSize; using WTF::fastRealloc; using WTF::fastStrDup; diff --git a/Source/WTF/wtf/FeatureDefines.h b/Source/WTF/wtf/FeatureDefines.h new file mode 100644 index 000000000..7329c95f5 --- /dev/null +++ b/Source/WTF/wtf/FeatureDefines.h @@ -0,0 +1,837 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved. + * Copyright (C) 2013 Samsung Electronics. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_FeatureDefines_h +#define WTF_FeatureDefines_h + +/* Use this file to list _all_ ENABLE() macros. Define the macros to be one of the following values: + * - "0" disables the feature by default. The feature can still be enabled for a specific port or environment. + * - "1" enables the feature by default. The feature can still be disabled for a specific port or environment. + * + * The feature defaults in this file are only taken into account if the (port specific) build system + * has not enabled or disabled a particular feature. + * + * Use this file to define ENABLE() macros only. Do not use this file to define USE() or macros ! + * + * Only define a macro if it was not defined before - always check for !defined first. + * + * Keep the file sorted by the name of the defines. As an exception you can change the order + * to allow interdependencies between the default values. + * + * Below are a few potential commands to take advantage of this file running from the Source/WTF directory + * + * Get the list of feature defines: grep -o "ENABLE_\(\w\+\)" wtf/FeatureDefines.h | sort | uniq + * Get the list of features enabled by default for a PLATFORM(XXX): gcc -E -dM -I. -DWTF_PLATFORM_XXX "wtf/Platform.h" | grep "ENABLE_\w\+ 1" | cut -d' ' -f2 | sort + */ + +/* FIXME: Move out the PLATFORM specific rules into platform specific files. */ + +/* --------- Apple IOS (but not MAC) port --------- */ +/* PLATFORM(IOS) is a specialization of PLATFORM(MAC). */ +/* PLATFORM(MAC) is always enabled when PLATFORM(IOS) is enabled. */ +#if PLATFORM(IOS) + +#if !defined(ENABLE_8BIT_TEXTRUN) +#define ENABLE_8BIT_TEXTRUN 1 +#endif + +#if !defined(ENABLE_CONTEXT_MENUS) +#define ENABLE_CONTEXT_MENUS 0 +#endif + +#if !defined(ENABLE_CSS_IMAGE_SET) +#define ENABLE_CSS_IMAGE_SET 1 +#endif + +#if !defined(ENABLE_DRAG_SUPPORT) +#define ENABLE_DRAG_SUPPORT 0 +#endif + +#if !defined(ENABLE_GEOLOCATION) +#define ENABLE_GEOLOCATION 1 +#endif + +#if !defined(ENABLE_ICONDATABASE) +#define ENABLE_ICONDATABASE 0 +#endif + +#if !defined(ENABLE_NETSCAPE_PLUGIN_API) +#define ENABLE_NETSCAPE_PLUGIN_API 0 +#endif + +#if !defined(ENABLE_ORIENTATION_EVENTS) +#define ENABLE_ORIENTATION_EVENTS 1 +#endif + +#if !defined(ENABLE_REPAINT_THROTTLING) +#define ENABLE_REPAINT_THROTTLING 1 +#endif + +#if !defined(ENABLE_TEXT_CARET) +#define ENABLE_TEXT_CARET 0 +#endif + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 1 +#endif + +#if !defined(ENABLE_VIEW_MODE_CSS_MEDIA) +#define ENABLE_VIEW_MODE_CSS_MEDIA 0 +#endif + +#if !defined(ENABLE_WEBGL) +#define ENABLE_WEBGL 1 +#endif + +#endif /* PLATFORM(IOS) */ + +/* --------- Apple MAC port (not IOS) --------- */ +#if PLATFORM(MAC) && !PLATFORM(IOS) + +#if !defined(ENABLE_8BIT_TEXTRUN) +#define ENABLE_8BIT_TEXTRUN 1 +#endif + +#if !defined(ENABLE_CSS_IMAGE_SET) +#define ENABLE_CSS_IMAGE_SET 1 +#endif + +#if !defined(ENABLE_DASHBOARD_SUPPORT) +#define ENABLE_DASHBOARD_SUPPORT 1 +#endif + +#if !defined(ENABLE_DELETION_UI) +#define ENABLE_DELETION_UI 1 +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#if !defined(ENABLE_ENCRYPTED_MEDIA) +#define ENABLE_ENCRYPTED_MEDIA 1 +#endif +#if !defined(ENABLE_ENCRYPTED_MEDIA_V2) +#define ENABLE_ENCRYPTED_MEDIA_V2 1 +#endif +#endif + +#if !defined(ENABLE_FULLSCREEN_API) +#define ENABLE_FULLSCREEN_API 1 +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +#if !defined(ENABLE_GESTURE_EVENTS) +#define ENABLE_GESTURE_EVENTS 1 +#endif +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +#if !defined(ENABLE_RUBBER_BANDING) +#define ENABLE_RUBBER_BANDING 1 +#endif +#endif + +#if !defined(ENABLE_SMOOTH_SCROLLING) +#define ENABLE_SMOOTH_SCROLLING 1 +#endif + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#if !defined(ENABLE_THREADED_SCROLLING) +#define ENABLE_THREADED_SCROLLING 1 +#endif +#endif + +#if ENABLE(VIDEO) +#if !defined(ENABLE_VIDEO_TRACK) +#define ENABLE_VIDEO_TRACK 1 +#endif +#endif + +#if !defined(ENABLE_VIEW_MODE_CSS_MEDIA) +#define ENABLE_VIEW_MODE_CSS_MEDIA 0 +#endif + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 1 +#endif + +#if !defined(ENABLE_WEB_AUDIO) +#define ENABLE_WEB_AUDIO 1 +#endif + +#if !defined(ENABLE_CURSOR_VISIBILITY) +#define ENABLE_CURSOR_VISIBILITY 1 +#endif + +#endif /* PLATFORM(MAC) && !PLATFORM(IOS) */ + +/* --------- Apple Windows port --------- */ +#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO) + +#if !defined(ENABLE_FULLSCREEN_API) +#define ENABLE_FULLSCREEN_API 1 +#endif + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 1 +#endif + +#endif /* PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO) */ + +/* --------- WinCE port --------- */ +/* WinCE port is a specialization of PLATFORM(WIN). */ +/* PLATFORM(WIN) is always enabled when building for the WinCE port. */ +#if PLATFORM(WIN) && OS(WINCE) + +#if !defined(ENABLE_DRAG_SUPPORT) +#define ENABLE_DRAG_SUPPORT 0 +#endif + +#if !defined(ENABLE_FTPDIR) +#define ENABLE_FTPDIR 0 +#endif + +#if !defined(ENABLE_INSPECTOR) +#define ENABLE_INSPECTOR 0 +#endif + +#endif /* PLATFORM(WIN) && OS(WINCE) */ + +/* --------- Windows CAIRO port --------- */ +/* PLATFORM(WIN_CAIRO) is a specialization of PLATFORM(WIN). */ +/* PLATFORM(WIN) is always enabled when PLATFORM(WIN_CAIRO) is enabled. */ +#if PLATFORM(WIN_CAIRO) + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 1 +#endif + +#if !defined(ENABLE_VIEW_MODE_CSS_MEDIA) +#define ENABLE_VIEW_MODE_CSS_MEDIA 0 +#endif + +#endif /* PLATFORM(WIN_CAIRO) */ + +/* --------- EFL port (Unix) --------- */ +#if PLATFORM(EFL) + +#if !defined(ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 +#endif + +#if !defined(ENABLE_SUBPIXEL_LAYOUT) +#define ENABLE_SUBPIXEL_LAYOUT 1 +#endif + +#endif /* PLATFORM(EFL) */ + +/* --------- Gtk port (Unix, Windows, Mac) --------- */ +#if PLATFORM(GTK) + +#if OS(UNIX) +#if !defined(ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 +#endif +#endif + +#endif /* PLATFORM(GTK) */ + +/* --------- Qt port (Unix, Windows, Mac, WinCE) --------- */ +#if PLATFORM(QT) + +#if OS(UNIX) +#if !defined(ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 +#endif +#endif + +#endif /* PLATFORM(QT) */ + +/* --------- Blackberry port (QNX) --------- */ +#if PLATFORM(BLACKBERRY) + +#if !defined(ENABLE_BLACKBERRY_CREDENTIAL_PERSIST) +#define ENABLE_BLACKBERRY_CREDENTIAL_PERSIST 1 +#endif + +#endif /* PLATFORM(BLACKBERRY) */ + +/* ENABLE macro defaults for WebCore */ +/* Do not use PLATFORM() tests in this section ! */ + +#if !defined(ENABLE_3D_RENDERING) +#define ENABLE_3D_RENDERING 0 +#endif + +#if !defined(ENABLE_8BIT_TEXTRUN) +#define ENABLE_8BIT_TEXTRUN 0 +#endif + +#if !defined(ENABLE_ACCELERATED_2D_CANVAS) +#define ENABLE_ACCELERATED_2D_CANVAS 0 +#endif + +#if !defined(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) +#define ENABLE_ACCELERATED_OVERFLOW_SCROLLING 0 +#endif + +#if !defined(ENABLE_BATTERY_STATUS) +#define ENABLE_BATTERY_STATUS 0 +#endif + +#if !defined(ENABLE_BLOB) +#define ENABLE_BLOB 0 +#endif + +#if !defined(ENABLE_CANVAS_PATH) +#define ENABLE_CANVAS_PATH 1 +#endif + +#if !defined(ENABLE_CANVAS_PROXY) +#define ENABLE_CANVAS_PROXY 0 +#endif + +#if !defined(ENABLE_CHANNEL_MESSAGING) +#define ENABLE_CHANNEL_MESSAGING 1 +#endif + +#if !defined(ENABLE_CONTEXT_MENUS) +#define ENABLE_CONTEXT_MENUS 1 +#endif + +#if !defined(ENABLE_CSP_NEXT) +#define ENABLE_CSP_NEXT 0 +#endif + +#if !defined(ENABLE_CSS3_CONDITIONAL_RULES) +#define ENABLE_CSS3_CONDITIONAL_RULES 0 +#endif + +#if !defined(ENABLE_CSS3_TEXT) +#define ENABLE_CSS3_TEXT 0 +#endif + +#if !defined(ENABLE_CSS_BOX_DECORATION_BREAK) +#define ENABLE_CSS_BOX_DECORATION_BREAK 1 +#endif + +#if !defined(ENABLE_CSS_DEVICE_ADAPTATION) +#define ENABLE_CSS_DEVICE_ADAPTATION 0 +#endif + +#if !defined(ENABLE_CSS_COMPOSITING) +#define ENABLE_CSS_COMPOSITING 0 +#endif + +#if !defined(ENABLE_CSS_FILTERS) +#define ENABLE_CSS_FILTERS 0 +#endif + +#if !defined(ENABLE_CSS_IMAGE_ORIENTATION) +#define ENABLE_CSS_IMAGE_ORIENTATION 0 +#endif + +#if !defined(ENABLE_CSS_IMAGE_RESOLUTION) +#define ENABLE_CSS_IMAGE_RESOLUTION 0 +#endif + +#if !defined(ENABLE_CSS_IMAGE_SET) +#define ENABLE_CSS_IMAGE_SET 0 +#endif + +#if !defined(ENABLE_CSS_SHADERS) +#define ENABLE_CSS_SHADERS 0 +#endif + +#if !defined(ENABLE_CSS_STICKY_POSITION) +#define ENABLE_CSS_STICKY_POSITION 0 +#endif + +#if !defined(ENABLE_CSS_TRANSFORMS_ANIMATIONS_TRANSITIONS_UNPREFIXED) +#define ENABLE_CSS_TRANSFORMS_ANIMATIONS_TRANSITIONS_UNPREFIXED 0 +#endif + +#if !defined(ENABLE_CSS_VARIABLES) +#define ENABLE_CSS_VARIABLES 0 +#endif + +#if !defined(ENABLE_CUSTOM_SCHEME_HANDLER) +#define ENABLE_CUSTOM_SCHEME_HANDLER 0 +#endif + +#if !defined(ENABLE_DASHBOARD_SUPPORT) +#define ENABLE_DASHBOARD_SUPPORT 0 +#endif + +#if !defined(ENABLE_DATALIST_ELEMENT) +#define ENABLE_DATALIST_ELEMENT 0 +#endif + +#if !defined(ENABLE_DATA_TRANSFER_ITEMS) +#define ENABLE_DATA_TRANSFER_ITEMS 0 +#endif + +#if !defined(ENABLE_DELETION_UI) +#define ENABLE_DELETION_UI 0 +#endif + +#if !defined(ENABLE_DETAILS_ELEMENT) +#define ENABLE_DETAILS_ELEMENT 1 +#endif + +#if !defined(ENABLE_DEVICE_ORIENTATION) +#define ENABLE_DEVICE_ORIENTATION 0 +#endif + +#if !defined(ENABLE_DIALOG_ELEMENT) +#define ENABLE_DIALOG_ELEMENT 0 +#endif + +#if !defined(ENABLE_DIRECTORY_UPLOAD) +#define ENABLE_DIRECTORY_UPLOAD 0 +#endif + +#if !defined(ENABLE_DOWNLOAD_ATTRIBUTE) +#define ENABLE_DOWNLOAD_ATTRIBUTE 0 +#endif + +#if !defined(ENABLE_DRAGGABLE_REGION) +#define ENABLE_DRAGGABLE_REGION 0 +#endif + +#if !defined(ENABLE_DRAG_SUPPORT) +#define ENABLE_DRAG_SUPPORT 1 +#endif + +#if !defined(ENABLE_ENCRYPTED_MEDIA) +#define ENABLE_ENCRYPTED_MEDIA 0 +#endif + +#if !defined(ENABLE_ENCRYPTED_MEDIA_V2) +#define ENABLE_ENCRYPTED_MEDIA_V2 0 +#endif + +#if !defined(ENABLE_FAST_MOBILE_SCROLLING) +#define ENABLE_FAST_MOBILE_SCROLLING 0 +#endif + +#if !defined(ENABLE_FILE_SYSTEM) +#define ENABLE_FILE_SYSTEM 0 +#endif + +#if !defined(ENABLE_FILTERS) +#define ENABLE_FILTERS 0 +#endif + +#if !defined(ENABLE_FONT_LOAD_EVENTS) +#define ENABLE_FONT_LOAD_EVENTS 0 +#endif + +#if !defined(ENABLE_FTPDIR) +#define ENABLE_FTPDIR 1 +#endif + +#if !defined(ENABLE_FULLSCREEN_API) +#define ENABLE_FULLSCREEN_API 0 +#endif + +#if !defined(ENABLE_GAMEPAD) +#define ENABLE_GAMEPAD 0 +#endif + +#if !defined(ENABLE_GEOLOCATION) +#define ENABLE_GEOLOCATION 0 +#endif + +#if !defined(ENABLE_GESTURE_EVENTS) +#define ENABLE_GESTURE_EVENTS 0 +#endif + +#if !defined(ENABLE_GLIB_SUPPORT) +#define ENABLE_GLIB_SUPPORT 0 +#endif + +#if !defined(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING) +#define ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING 0 +#endif + +#if !defined(ENABLE_HIGH_DPI_CANVAS) +#define ENABLE_HIGH_DPI_CANVAS 0 +#endif + +#if !defined(ENABLE_ICONDATABASE) +#define ENABLE_ICONDATABASE 1 +#endif + +#if !defined(ENABLE_IFRAME_SEAMLESS) +#define ENABLE_IFRAME_SEAMLESS 1 +#endif + +#if !defined(ENABLE_IMAGE_DECODER_DOWN_SAMPLING) +#define ENABLE_IMAGE_DECODER_DOWN_SAMPLING 0 +#endif + +#if !defined(ENABLE_INDEXED_DATABASE) +#define ENABLE_INDEXED_DATABASE 0 +#endif + +#if !defined(ENABLE_INPUT_SPEECH) +#define ENABLE_INPUT_SPEECH 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_COLOR) +#define ENABLE_INPUT_TYPE_COLOR 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_DATE) +#define ENABLE_INPUT_TYPE_DATE 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE) +#define ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_DATETIMELOCAL) +#define ENABLE_INPUT_TYPE_DATETIMELOCAL 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_MONTH) +#define ENABLE_INPUT_TYPE_MONTH 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_TIME) +#define ENABLE_INPUT_TYPE_TIME 0 +#endif + +#if !defined(ENABLE_INPUT_TYPE_WEEK) +#define ENABLE_INPUT_TYPE_WEEK 0 +#endif + +#if ENABLE(INPUT_TYPE_DATE) || ENABLE(INPUT_TYPE_DATETIME_INCOMPLETE) || ENABLE(INPUT_TYPE_DATETIMELOCAL) || ENABLE(INPUT_TYPE_MONTH) || ENABLE(INPUT_TYPE_TIME) || ENABLE(INPUT_TYPE_WEEK) +#if !defined(ENABLE_DATE_AND_TIME_INPUT_TYPES) +#define ENABLE_DATE_AND_TIME_INPUT_TYPES 1 +#endif +#endif + +#if !defined(ENABLE_INSPECTOR) +#define ENABLE_INSPECTOR 1 +#endif + +#if !defined(ENABLE_JAVASCRIPT_DEBUGGER) +#define ENABLE_JAVASCRIPT_DEBUGGER 1 +#endif + +#if !defined(ENABLE_JAVASCRIPT_I18N_API) +#define ENABLE_JAVASCRIPT_I18N_API 0 +#endif + +#if !defined(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) +#define ENABLE_LEGACY_CSS_VENDOR_PREFIXES 0 +#endif + +#if !defined(ENABLE_LEGACY_NOTIFICATIONS) +#define ENABLE_LEGACY_NOTIFICATIONS 0 +#endif + +#if !defined(ENABLE_LEGACY_VENDOR_PREFIXES) +#define ENABLE_LEGACY_VENDOR_PREFIXES 0 +#endif + +#if !defined(ENABLE_LEGACY_VIEWPORT_ADAPTION) +#define ENABLE_LEGACY_VIEWPORT_ADAPTION 0 +#endif + +#if !defined(ENABLE_LINK_PREFETCH) +#define ENABLE_LINK_PREFETCH 0 +#endif + +#if !defined(ENABLE_MATHML) +#define ENABLE_MATHML 1 +#endif + +#if !defined(ENABLE_MEDIA_CAPTURE) +#define ENABLE_MEDIA_CAPTURE 0 +#endif + +#if !defined(ENABLE_MEDIA_SOURCE) +#define ENABLE_MEDIA_SOURCE 0 +#endif + +#if !defined(ENABLE_MEDIA_STATISTICS) +#define ENABLE_MEDIA_STATISTICS 0 +#endif + +#if !defined(ENABLE_MEDIA_STREAM) +#define ENABLE_MEDIA_STREAM 0 +#endif + +#if !defined(ENABLE_METER_ELEMENT) +#define ENABLE_METER_ELEMENT 1 +#endif + +#if !defined(ENABLE_MHTML) +#define ENABLE_MHTML 0 +#endif + +#if !defined(ENABLE_MICRODATA) +#define ENABLE_MICRODATA 0 +#endif + +#if !defined(ENABLE_MOUSE_CURSOR_SCALE) +#define ENABLE_MOUSE_CURSOR_SCALE 0 +#endif + +#if !defined(ENABLE_NAVIGATOR_CONTENT_UTILS) +#define ENABLE_NAVIGATOR_CONTENT_UTILS 0 +#endif + +#if !defined(ENABLE_NETSCAPE_PLUGIN_API) +#define ENABLE_NETSCAPE_PLUGIN_API 1 +#endif + +#if !defined(ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE) +#define ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE 0 +#endif + +#if !defined(ENABLE_NETWORK_INFO) +#define ENABLE_NETWORK_INFO 0 +#endif + +#if !defined(ENABLE_NOTIFICATIONS) +#define ENABLE_NOTIFICATIONS 0 +#endif + +#if !defined(ENABLE_OBJECT_MARK_LOGGING) +#define ENABLE_OBJECT_MARK_LOGGING 0 +#endif + +#if !defined(ENABLE_OPENCL) +#define ENABLE_OPENCL 0 +#endif + +#if !defined(ENABLE_OPENTYPE_VERTICAL) +#define ENABLE_OPENTYPE_VERTICAL 0 +#endif + +#if !defined(ENABLE_ORIENTATION_EVENTS) +#define ENABLE_ORIENTATION_EVENTS 0 +#endif + +#if !defined(ENABLE_PAGE_VISIBILITY_API) +#define ENABLE_PAGE_VISIBILITY_API 0 +#endif + +#if OS(WINDOWS) +#if !defined(ENABLE_PAN_SCROLLING) +#define ENABLE_PAN_SCROLLING 1 +#endif +#endif + +#if !defined(ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 0 +#endif + +#if !defined(ENABLE_PLUGIN_PROXY_FOR_VIDEO) +#define ENABLE_PLUGIN_PROXY_FOR_VIDEO 0 +#endif + +#if !defined(ENABLE_POINTER_LOCK) +#define ENABLE_POINTER_LOCK 0 +#endif + +#if !defined(ENABLE_PROGRESS_ELEMENT) +#define ENABLE_PROGRESS_ELEMENT 0 +#endif + +#if !defined(ENABLE_PROXIMITY_EVENTS) +#define ENABLE_PROXIMITY_EVENTS 0 +#endif + +#if !defined(ENABLE_QUOTA) +#define ENABLE_QUOTA 0 +#endif + +#if !defined(ENABLE_REPAINT_THROTTLING) +#define ENABLE_REPAINT_THROTTLING 0 +#endif + +#if !defined(ENABLE_REQUEST_ANIMATION_FRAME) +#define ENABLE_REQUEST_ANIMATION_FRAME 0 +#endif + +#if !defined(ENABLE_RUBBER_BANDING) +#define ENABLE_RUBBER_BANDING 0 +#endif + +#if !defined(ENABLE_SATURATED_LAYOUT_ARITHMETIC) +#define ENABLE_SATURATED_LAYOUT_ARITHMETIC 0 +#endif + +#if !defined(ENABLE_SCRIPTED_SPEECH) +#define ENABLE_SCRIPTED_SPEECH 0 +#endif + +#if !defined(ENABLE_SHADOW_DOM) +#define ENABLE_SHADOW_DOM 0 +#endif + +#if !defined(ENABLE_SHARED_WORKERS) +#define ENABLE_SHARED_WORKERS 0 +#endif + +#if !defined(ENABLE_SMOOTH_SCROLLING) +#define ENABLE_SMOOTH_SCROLLING 0 +#endif + +#if !defined(ENABLE_SPEECH_SYNTHESIS) +#define ENABLE_SPEECH_SYNTHESIS 0 +#endif + +#if !defined(ENABLE_SPELLCHECK) +#define ENABLE_SPELLCHECK 0 +#endif + +#if !defined(ENABLE_SQL_DATABASE) +#define ENABLE_SQL_DATABASE 1 +#endif + +#if !defined(ENABLE_STYLE_SCOPED) +#define ENABLE_STYLE_SCOPED 0 +#endif + +#if !defined(ENABLE_SUBPIXEL_LAYOUT) +#define ENABLE_SUBPIXEL_LAYOUT 0 +#endif + +#if !defined(ENABLE_SVG) +#define ENABLE_SVG 1 +#endif + +#if ENABLE(SVG) +#if !defined(ENABLE_SVG_FONTS) +#define ENABLE_SVG_FONTS 1 +#endif +#endif + +#if !defined(ENABLE_TEMPLATE_ELEMENT) +#define ENABLE_TEMPLATE_ELEMENT 0 +#endif + +#if !defined(ENABLE_TEXT_AUTOSIZING) +#define ENABLE_TEXT_AUTOSIZING 0 +#endif + +#if !defined(ENABLE_TEXT_CARET) +#define ENABLE_TEXT_CARET 1 +#endif + +#if !defined(ENABLE_THREADED_HTML_PARSER) +#define ENABLE_THREADED_HTML_PARSER 0 +#endif + +#if !defined(ENABLE_THREADED_SCROLLING) +#define ENABLE_THREADED_SCROLLING 0 +#endif + +#if !defined(ENABLE_TOUCH_EVENTS) +#define ENABLE_TOUCH_EVENTS 0 +#endif + +#if !defined(ENABLE_TOUCH_ICON_LOADING) +#define ENABLE_TOUCH_ICON_LOADING 0 +#endif + +#if !defined(ENABLE_VIBRATION) +#define ENABLE_VIBRATION 0 +#endif + +#if !defined(ENABLE_VIDEO) +#define ENABLE_VIDEO 0 +#endif + +#if !defined(ENABLE_VIDEO_TRACK) +#define ENABLE_VIDEO_TRACK 0 +#endif + +#if !defined(ENABLE_VIEWPORT) +#define ENABLE_VIEWPORT 0 +#endif + +#if !defined(ENABLE_VIEWSOURCE_ATTRIBUTE) +#define ENABLE_VIEWSOURCE_ATTRIBUTE 1 +#endif + +#if !defined(ENABLE_VIEW_MODE_CSS_MEDIA) +#define ENABLE_VIEW_MODE_CSS_MEDIA 1 +#endif + +#if !defined(ENABLE_WEBGL) +#define ENABLE_WEBGL 0 +#endif + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 0 +#endif + +#if !defined(ENABLE_WEB_AUDIO) +#define ENABLE_WEB_AUDIO 0 +#endif + +#if !defined(ENABLE_WEB_SOCKETS) +#define ENABLE_WEB_SOCKETS 1 +#endif + +#if !defined(ENABLE_WEB_TIMING) +#define ENABLE_WEB_TIMING 0 +#endif + +#if !defined(ENABLE_WORKERS) +#define ENABLE_WORKERS 0 +#endif + +#if !defined(ENABLE_XHR_TIMEOUT) +#define ENABLE_XHR_TIMEOUT 0 +#endif + +#if !defined(ENABLE_XSLT) +#define ENABLE_XSLT 1 +#endif + +/* Asserts, invariants for macro definitions */ + +#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) && !ENABLE(SUBPIXEL_LAYOUT) +#error "ENABLE(SATURATED_LAYOUT_ARITHMETIC) requires ENABLE(SUBPIXEL_LAYOUT)" +#endif + +#if ENABLE(SVG_FONTS) && !ENABLE(SVG) +#error "ENABLE(SVG_FONTS) requires ENABLE(SVG)" +#endif + +#if ENABLE(VIDEO_TRACK) && !ENABLE(VIDEO) +#error "ENABLE(VIDEO_TRACK) requires ENABLE(VIDEO)" +#endif + +#endif /* WTF_FeatureDefines_h */ diff --git a/Source/WTF/wtf/FilePrintStream.cpp b/Source/WTF/wtf/FilePrintStream.cpp index 2deea6899..b5ab25e0b 100644 --- a/Source/WTF/wtf/FilePrintStream.cpp +++ b/Source/WTF/wtf/FilePrintStream.cpp @@ -41,6 +41,15 @@ FilePrintStream::~FilePrintStream() fclose(m_file); } +PassOwnPtr<FilePrintStream> FilePrintStream::open(const char* filename, const char* mode) +{ + FILE* file = fopen(filename, mode); + if (!file) + return PassOwnPtr<FilePrintStream>(); + + return adoptPtr(new FilePrintStream(file)); +} + void FilePrintStream::vprintf(const char* format, va_list argList) { vfprintf(m_file, format, argList); diff --git a/Source/WTF/wtf/FilePrintStream.h b/Source/WTF/wtf/FilePrintStream.h index c9af344ae..6a00f00ae 100644 --- a/Source/WTF/wtf/FilePrintStream.h +++ b/Source/WTF/wtf/FilePrintStream.h @@ -27,6 +27,7 @@ #define FilePrintStream_h #include <stdio.h> +#include <wtf/PassOwnPtr.h> #include <wtf/PrintStream.h> namespace WTF { @@ -41,6 +42,8 @@ public: FilePrintStream(FILE*, AdoptionMode = Adopt); virtual ~FilePrintStream(); + WTF_EXPORT_PRIVATE static PassOwnPtr<FilePrintStream> open(const char* filename, const char* mode); + FILE* file() { return m_file; } void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0); diff --git a/Source/WTF/wtf/FixedArray.h b/Source/WTF/wtf/FixedArray.h index c67d18cda..c50a12b9e 100644 --- a/Source/WTF/wtf/FixedArray.h +++ b/Source/WTF/wtf/FixedArray.h @@ -34,13 +34,13 @@ template <typename T, size_t Size> class FixedArray { public: T& operator[](size_t i) { - ASSERT(i < Size); + ASSERT_WITH_SECURITY_IMPLICATION(i < Size); return m_data[i]; } const T& operator[](size_t i) const { - ASSERT(i < Size); + ASSERT_WITH_SECURITY_IMPLICATION(i < Size); return m_data[i]; } diff --git a/Source/WTF/wtf/Float32Array.h b/Source/WTF/wtf/Float32Array.h index 47204ec78..6672a0aff 100644 --- a/Source/WTF/wtf/Float32Array.h +++ b/Source/WTF/wtf/Float32Array.h @@ -42,8 +42,7 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Float32Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<float>* array, unsigned offset) { return TypedArrayBase<float>::set(array, offset); } + using TypedArrayBase<float>::set; void set(unsigned index, double value) { diff --git a/Source/WTF/wtf/Float64Array.h b/Source/WTF/wtf/Float64Array.h index 1d9a9c82e..3a930ce00 100644 --- a/Source/WTF/wtf/Float64Array.h +++ b/Source/WTF/wtf/Float64Array.h @@ -42,8 +42,7 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Float64Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<double>* array, unsigned offset) { return TypedArrayBase<double>::set(array, offset); } + using TypedArrayBase<double>::set; void set(unsigned index, double value) { diff --git a/Source/WTF/wtf/Forward.h b/Source/WTF/wtf/Forward.h index 5c2acfe7a..82c2e181a 100644 --- a/Source/WTF/wtf/Forward.h +++ b/Source/WTF/wtf/Forward.h @@ -24,30 +24,31 @@ #include <stddef.h> namespace WTF { + template<typename T> class Function; - template<typename T> class ListRefPtr; template<typename T> class OwnArrayPtr; template<typename T> class OwnPtr; template<typename T> class PassOwnArrayPtr; template<typename T> class PassOwnPtr; template<typename T> class PassRefPtr; template<typename T> class RefPtr; - template<typename T, size_t inlineCapacity> class Vector; + template<typename T, size_t inlineCapacity, typename OverflowHandler> class Vector; class ArrayBuffer; class ArrayBufferView; class AtomicString; class AtomicStringImpl; + class BinarySemaphore; class CString; class Decoder; class Encoder; class Float32Array; class Float64Array; + class FunctionDispatcher; class Int8Array; class Int16Array; class Int32Array; - class MemoryInstrumentation; - class MemoryObjectInfo; + class PrintStream; class String; template <typename T> class StringBuffer; class StringBuilder; @@ -59,7 +60,6 @@ namespace WTF { } using WTF::Function; -using WTF::ListRefPtr; using WTF::OwnArrayPtr; using WTF::OwnPtr; using WTF::PassOwnArrayPtr; @@ -72,16 +72,17 @@ using WTF::ArrayBuffer; using WTF::ArrayBufferView; using WTF::AtomicString; using WTF::AtomicStringImpl; +using WTF::BinarySemaphore; using WTF::CString; using WTF::Encoder; using WTF::Decoder; using WTF::Float32Array; using WTF::Float64Array; +using WTF::FunctionDispatcher; using WTF::Int8Array; using WTF::Int16Array; using WTF::Int32Array; -using WTF::MemoryInstrumentation; -using WTF::MemoryObjectInfo; +using WTF::PrintStream; using WTF::String; using WTF::StringBuffer; using WTF::StringBuilder; diff --git a/Source/WTF/wtf/FunctionDispatcher.cpp b/Source/WTF/wtf/FunctionDispatcher.cpp new file mode 100644 index 000000000..250a1dec3 --- /dev/null +++ b/Source/WTF/wtf/FunctionDispatcher.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FunctionDispatcher.h" + +namespace WTF { + +FunctionDispatcher::FunctionDispatcher() +{ +} + +FunctionDispatcher::~FunctionDispatcher() +{ +} + +} // namespace WTF diff --git a/Source/WTF/wtf/FunctionDispatcher.h b/Source/WTF/wtf/FunctionDispatcher.h new file mode 100644 index 000000000..1d7ec0b76 --- /dev/null +++ b/Source/WTF/wtf/FunctionDispatcher.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <wtf/Forward.h> +#include <wtf/ThreadSafeRefCounted.h> + +namespace WTF { + +// FunctionDispatcher is an abstract representation of something that functions can be +// dispatched to. This can for example be a run loop or a work queue. + +class FunctionDispatcher : public ThreadSafeRefCounted<FunctionDispatcher> { +public: + WTF_EXPORT_PRIVATE virtual ~FunctionDispatcher(); + + virtual void dispatch(const Function<void ()>&) = 0; + +protected: + WTF_EXPORT_PRIVATE FunctionDispatcher(); +}; + +} // namespace WTF + +using WTF::FunctionDispatcher; diff --git a/Source/WTF/wtf/Functional.h b/Source/WTF/wtf/Functional.h index 828ac2f91..a2fc1586c 100644 --- a/Source/WTF/wtf/Functional.h +++ b/Source/WTF/wtf/Functional.h @@ -30,8 +30,9 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/ThreadSafeRefCounted.h> +#include <wtf/WeakPtr.h> -#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) +#if OS(DARWIN) && COMPILER_SUPPORTS(BLOCKS) #include <Block.h> #include <wtf/ObjcRuntimeExtras.h> #endif @@ -77,6 +78,8 @@ public: template<typename> class FunctionWrapper; +// Bound static functions: + template<typename R> class FunctionWrapper<R (*)()> { public: @@ -157,6 +160,48 @@ private: R (*m_function)(P1, P2, P3); }; +template<typename R, typename P1, typename P2, typename P3, typename P4> +class FunctionWrapper<R (*)(P1, P2, P3, P4)> { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)(P1, P2, P3, P4)) + : m_function(function) + { + } + + R operator()(P1 p1, P2 p2, P3 p3, P4 p4) + { + return m_function(p1, p2, p3, p4); + } + +private: + R (*m_function)(P1, P2, P3, P4); +}; + +template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5> +class FunctionWrapper<R (*)(P1, P2, P3, P4, P5)> { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)(P1, P2, P3, P4, P5)) + : m_function(function) + { + } + + R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + { + return m_function(p1, p2, p3, p4, p5); + } + +private: + R (*m_function)(P1, P2, P3, P4, P5); +}; + +// Bound member functions: + template<typename R, typename C> class FunctionWrapper<R (C::*)()> { public: @@ -173,6 +218,14 @@ public: return (c->*m_function)(); } + R operator()(const WeakPtr<C>& c) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(); + } + private: R (C::*m_function)(); }; @@ -193,6 +246,14 @@ public: return (c->*m_function)(p1); } + R operator()(const WeakPtr<C>& c, P1 p1) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(p1); + } + private: R (C::*m_function)(P1); }; @@ -213,6 +274,14 @@ public: return (c->*m_function)(p1, p2); } + R operator()(const WeakPtr<C>& c, P1 p1, P2 p2) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(p1, p2); + } + private: R (C::*m_function)(P1, P2); }; @@ -233,6 +302,14 @@ public: return (c->*m_function)(p1, p2, p3); } + R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(p1, p2, p3); + } + private: R (C::*m_function)(P1, P2, P3); }; @@ -253,6 +330,14 @@ public: return (c->*m_function)(p1, p2, p3, p4); } + R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3, P4 p4) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(p1, p2, p3, p4); + } + private: R (C::*m_function)(P1, P2, P3, P4); }; @@ -273,11 +358,19 @@ public: return (c->*m_function)(p1, p2, p3, p4, p5); } + R operator()(const WeakPtr<C>& c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + { + C* obj = c.get(); + if (!obj) + return R(); + return (obj->*m_function)(p1, p2, p3, p4, p5); + } + private: R (C::*m_function)(P1, P2, P3, P4, P5); }; -#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) +#if OS(DARWIN) && COMPILER_SUPPORTS(BLOCKS) template<typename R> class FunctionWrapper<R (^)()> { public: @@ -340,7 +433,6 @@ template<typename T> struct ParamStorageTraits<RefPtr<T> > { static T* unwrap(const StorageType& value) { return value.get(); } }; - template<typename> class RetainPtr; template<typename T> struct ParamStorageTraits<RetainPtr<T> > { @@ -375,7 +467,7 @@ public: { } - virtual R operator()() + virtual typename FunctionWrapper::ResultType operator()() { return m_functionWrapper(); } @@ -386,7 +478,6 @@ private: template<typename FunctionWrapper, typename R, typename P1> class BoundFunctionImpl<FunctionWrapper, R (P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { - public: BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1) : m_functionWrapper(functionWrapper) @@ -400,7 +491,7 @@ public: RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); } - virtual R operator()() + virtual typename FunctionWrapper::ResultType operator()() { return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1)); } @@ -613,7 +704,7 @@ public: return impl<R ()>()->operator()(); } -#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) +#if OS(DARWIN) && COMPILER_SUPPORTS(BLOCKS) typedef void (^BlockType)(); operator BlockType() const { diff --git a/Source/WTF/wtf/GregorianDateTime.cpp b/Source/WTF/wtf/GregorianDateTime.cpp index 61f73bf50..5560984e6 100644 --- a/Source/WTF/wtf/GregorianDateTime.cpp +++ b/Source/WTF/wtf/GregorianDateTime.cpp @@ -78,9 +78,7 @@ void GregorianDateTime::setToCurrentLocalTime() #if HAVE(TM_GMTOFF) m_utcOffset = localTM.tm_gmtoff; #else - int utcOffset = calculateUTCOffset(); - utcOffset += calculateDSTOffset(localTime * msPerSecond, utcOffset); - m_utcOffset = utcOffset / msPerSecond; + m_utcOffset = calculateLocalTimeOffset(localTime * msPerSecond).offset / msPerSecond; #endif #endif } diff --git a/Source/WTF/wtf/HashMap.h b/Source/WTF/wtf/HashMap.h index 254554458..708e8d838 100644 --- a/Source/WTF/wtf/HashMap.h +++ b/Source/WTF/wtf/HashMap.h @@ -117,9 +117,9 @@ namespace WTF { // must have the following function members: // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); - template<typename T, typename HashTranslator> iterator find(const T&); - template<typename T, typename HashTranslator> const_iterator find(const T&) const; - template<typename T, typename HashTranslator> bool contains(const T&) const; + template<typename HashTranslator, typename T> iterator find(const T&); + template<typename HashTranslator, typename T> const_iterator find(const T&) const; + template<typename HashTranslator, typename T> bool contains(const T&) const; // An alternate version of add() that finds the object by hashing and comparing // with some other type, to avoid the cost of type conversion if the object is already @@ -127,10 +127,12 @@ namespace WTF { // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); // static translate(ValueType&, const T&, unsigned hashCode); - template<typename T, typename HashTranslator> AddResult add(const T&, MappedPassInType); + template<typename HashTranslator, typename T> AddResult add(const T&, MappedPassInType); void checkConsistency() const; + static bool isValidKey(const KeyType&); + private: AddResult inlineAdd(const KeyType&, MappedPassInReferenceType); @@ -138,7 +140,7 @@ namespace WTF { }; template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> - class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapKeysProxy : + class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapKeysProxy : private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { public: typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; @@ -176,7 +178,7 @@ namespace WTF { }; template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> - class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapValuesProxy : + class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::HashMapValuesProxy : private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { public: typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; @@ -310,7 +312,7 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> + template<typename HashTranslator, typename TYPE> inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const TYPE& value) { @@ -318,7 +320,7 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> + template<typename HashTranslator, typename TYPE> inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const TYPE& value) const { @@ -326,7 +328,7 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> + template<typename HashTranslator, typename TYPE> inline bool HashMap<T, U, V, W, X>::contains(const TYPE& value) const { @@ -353,7 +355,7 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> + template<typename HashTranslator, typename TYPE> typename HashMap<T, U, V, W, X>::AddResult HashMap<T, U, V, W, X>::add(const TYPE& key, MappedPassInType value) { @@ -417,6 +419,23 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> + inline bool HashMap<T, U, V, W, X>::isValidKey(const KeyType& key) + { + if (KeyTraits::isDeletedValue(key)) + return false; + + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (key == KeyTraits::emptyValue()) + return false; + } else { + if (isHashTraitsEmptyValue<KeyTraits>(key)) + return false; + } + + return true; + } + + template<typename T, typename U, typename V, typename W, typename X> bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) { if (a.size() != b.size()) @@ -449,15 +468,6 @@ namespace WTF { for (iterator it = collection.begin(); it != end; ++it) delete it->value; } - - template<typename T, typename U, typename V, typename W, typename X> - inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection) - { - typedef typename HashMap<T, U, V, W, X>::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete it->key; - } template<typename T, typename U, typename V, typename W, typename X, typename Y> inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) diff --git a/Source/WTF/wtf/HashSet.h b/Source/WTF/wtf/HashSet.h index 40bd7fe4c..c89d40f30 100644 --- a/Source/WTF/wtf/HashSet.h +++ b/Source/WTF/wtf/HashSet.h @@ -68,10 +68,8 @@ namespace WTF { // must have the following function members: // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); - // FIXME: We should reverse the order of the template arguments so that callers - // can just pass the translator and let the compiler deduce T. - template<typename T, typename HashTranslator> iterator find(const T&) const; - template<typename T, typename HashTranslator> bool contains(const T&) const; + template<typename HashTranslator, typename T> iterator find(const T&) const; + template<typename HashTranslator, typename T> bool contains(const T&) const; // The return value is a pair of an interator to the new value's location, // and a bool that is true if an new entry was added. @@ -83,14 +81,14 @@ namespace WTF { // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); // static translate(ValueType&, const T&, unsigned hashCode); - // FIXME: We should reverse the order of the template arguments so that callers - // can just pass the translator and let the compiler deduce T. - template<typename T, typename HashTranslator> AddResult add(const T&); + template<typename HashTranslator, typename T> AddResult add(const T&); void remove(const ValueType&); void remove(iterator); void clear(); + static bool isValidValue(const ValueType&); + private: friend void deleteAllValues<>(const HashSet&); @@ -160,7 +158,7 @@ namespace WTF { } template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> + template<typename HashTranslator, typename T> typename HashSet<Value, HashFunctions, Traits>::iterator inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const { @@ -168,7 +166,7 @@ namespace WTF { } template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> + template<typename HashTranslator, typename T> inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const { return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator> >(value); @@ -181,7 +179,7 @@ namespace WTF { } template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> + template<typename HashTranslator, typename T> inline typename HashSet<Value, HashFunctions, Traits>::AddResult HashSet<Value, HashFunctions, Traits>::add(const T& value) { @@ -209,6 +207,23 @@ namespace WTF { m_impl.clear(); } + template<typename T, typename U, typename V> + inline bool HashSet<T, U, V>::isValidValue(const ValueType& value) + { + if (ValueTraits::isDeletedValue(value)) + return false; + + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (value == ValueTraits::emptyValue()) + return false; + } else { + if (isHashTraitsEmptyValue<ValueTraits>(value)) + return false; + } + + return true; + } + template<typename ValueType, typename HashTableType> void deleteAllValues(HashTableType& collection) { @@ -224,10 +239,10 @@ namespace WTF { deleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl); } - template<typename T, typename U, typename V, typename W> - inline void copyToVector(const HashSet<T, U, V>& collection, W& vector) + template<typename C, typename W> + inline void copyToVector(const C& collection, W& vector) { - typedef typename HashSet<T, U, V>::const_iterator iterator; + typedef typename C::const_iterator iterator; vector.resize(collection.size()); diff --git a/Source/WTF/wtf/HashTable.h b/Source/WTF/wtf/HashTable.h index 6e51b4507..46ba790a2 100644 --- a/Source/WTF/wtf/HashTable.h +++ b/Source/WTF/wtf/HashTable.h @@ -24,7 +24,6 @@ #include <wtf/Alignment.h> #include <wtf/Assertions.h> -#include <wtf/DataLog.h> #include <wtf/FastMalloc.h> #include <wtf/HashTraits.h> #include <wtf/StdLibExtras.h> @@ -37,11 +36,15 @@ #include <wtf/PassOwnPtr.h> #endif -namespace WTF { - #define DUMP_HASHTABLE_STATS 0 #define DUMP_HASHTABLE_STATS_PER_TABLE 0 +#if DUMP_HASHTABLE_STATS_PER_TABLE +#include <wtf/DataLog.h> +#endif + +namespace WTF { + // Enables internal WTF consistency checks that are invoked automatically. Non-WTF callers can call checkTableConsistency() even if internal checks are disabled. #define CHECK_HASHTABLE_CONSISTENCY 0 @@ -297,7 +300,7 @@ namespace WTF { template<typename HashFunctions> class IdentityHashTranslator { public: template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } - template<typename T> static bool equal(const T& a, const T& b) { return HashFunctions::equal(a, b); } + template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } template<typename T, typename U> static void translate(T& location, const U&, const T& value) { location = value; } }; diff --git a/Source/WTF/wtf/HashTraits.h b/Source/WTF/wtf/HashTraits.h index 88034087c..636587c97 100644 --- a/Source/WTF/wtf/HashTraits.h +++ b/Source/WTF/wtf/HashTraits.h @@ -78,12 +78,14 @@ namespace WTF { // Type for return value of functions that transfer ownership, such as take. typedef T PassOutType; static PassOutType passOut(const T& value) { return value; } + static T& passOut(T& value) { return value; } // Overloaded to avoid copying of non-temporary values. // Type for return value of functions that do not transfer ownership, such as get. // FIXME: We could change this type to const T& for better performance if we figured out // a way to handle the return value from emptyValue, which is a temporary. typedef T PeekType; static PeekType peek(const T& value) { return value; } + static T& peek(T& value) { return value; } // Overloaded to avoid copying of non-temporary values. }; template<typename T> struct HashTraits : GenericHashTraits<T> { }; @@ -138,12 +140,18 @@ namespace WTF { }; template<typename P> struct HashTraits<RefPtr<P> > : SimpleClassHashTraits<RefPtr<P> > { + static P* emptyValue() { return 0; } + typedef PassRefPtr<P> PassInType; static void store(PassRefPtr<P> value, RefPtr<P>& storage) { storage = value; } - // FIXME: We should change PassOutType to PassRefPtr for better performance. - // FIXME: We should consider changing PeekType to a raw pointer for better performance, - // but then callers won't need to call get; doing so will require updating many call sites. + typedef PassRefPtr<P> PassOutType; + static PassRefPtr<P> passOut(RefPtr<P>& value) { return value.release(); } + static PassRefPtr<P> passOut(P* value) { return value; } + + typedef P* PeekType; + static PeekType peek(const RefPtr<P>& value) { return value.get(); } + static PeekType peek(P* value) { return value; } }; template<> struct HashTraits<String> : SimpleClassHashTraits<String> { @@ -243,5 +251,6 @@ namespace WTF { using WTF::HashTraits; using WTF::PairHashTraits; using WTF::NullableHashTraits; +using WTF::SimpleClassHashTraits; #endif // WTF_HashTraits_h diff --git a/Source/WTF/wtf/HexNumber.h b/Source/WTF/wtf/HexNumber.h index a198b92cd..b698dd50e 100644 --- a/Source/WTF/wtf/HexNumber.h +++ b/Source/WTF/wtf/HexNumber.h @@ -31,9 +31,9 @@ enum HexConversionMode { namespace Internal { -const char lowerHexDigits[17] = "0123456789abcdef"; -const char upperHexDigits[17] = "0123456789ABCDEF"; -inline const char* hexDigitsForMode(HexConversionMode mode) +const LChar lowerHexDigits[17] = "0123456789abcdef"; +const LChar upperHexDigits[17] = "0123456789ABCDEF"; +inline const LChar* hexDigitsForMode(HexConversionMode mode) { return mode == Lowercase ? lowerHexDigits : upperHexDigits; } @@ -43,7 +43,7 @@ inline const char* hexDigitsForMode(HexConversionMode mode) template<typename T> inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) { - const char* hexDigits = Internal::hexDigitsForMode(mode); + const LChar* hexDigits = Internal::hexDigitsForMode(mode); destination.append(hexDigits[byte >> 4]); destination.append(hexDigits[byte & 0xF]); } @@ -51,7 +51,7 @@ inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMod template<typename T> inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase) { - const char* hexDigits = Internal::hexDigitsForMode(mode); + const LChar* hexDigits = Internal::hexDigitsForMode(mode); if (byte >= 0x10) destination[index++] = hexDigits[byte >> 4]; destination[index++] = hexDigits[byte & 0xF]; @@ -60,7 +60,7 @@ inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, template<typename T> inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) { - const char* hexDigits = Internal::hexDigitsForMode(mode); + const LChar* hexDigits = Internal::hexDigitsForMode(mode); *destination++ = hexDigits[byte >> 4]; *destination++ = hexDigits[byte & 0xF]; } @@ -68,13 +68,14 @@ inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode template<typename T> inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase) { - const char* hexDigits = Internal::hexDigitsForMode(mode); - Vector<UChar, 8> result; + const LChar* hexDigits = Internal::hexDigitsForMode(mode); + Vector<LChar, 8> result; do { - result.prepend(hexDigits[number % 16]); + result.append(hexDigits[number % 16]); number >>= 4; } while (number > 0); + result.reverse(); destination.append(result.data(), result.size()); } @@ -84,14 +85,15 @@ inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsign { ASSERT(desiredDigits); - const char* hexDigits = Internal::hexDigitsForMode(mode); - Vector<UChar, 8> result; + const LChar* hexDigits = Internal::hexDigitsForMode(mode); + Vector<LChar, 8> result; do { - result.prepend(hexDigits[number % 16]); + result.append(hexDigits[number % 16]); number >>= 4; } while (result.size() < desiredDigits); ASSERT(result.size() == desiredDigits); + result.reverse(); destination.append(result.data(), result.size()); } diff --git a/Source/WTF/wtf/Int16Array.h b/Source/WTF/wtf/Int16Array.h index be9858388..7d5a579a7 100644 --- a/Source/WTF/wtf/Int16Array.h +++ b/Source/WTF/wtf/Int16Array.h @@ -42,9 +42,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Int16Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<short>* array, unsigned offset) { return TypedArrayBase<short>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<short>::set(index, value); } + using TypedArrayBase<short>::set; + using IntegralTypedArrayBase<short>::set; inline PassRefPtr<Int16Array> subarray(int start) const; inline PassRefPtr<Int16Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/Int32Array.h b/Source/WTF/wtf/Int32Array.h index 99bce1ad2..45a997809 100644 --- a/Source/WTF/wtf/Int32Array.h +++ b/Source/WTF/wtf/Int32Array.h @@ -41,9 +41,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Int32Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<int>* array, unsigned offset) { return TypedArrayBase<int>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<int>::set(index, value); } + using TypedArrayBase<int>::set; + using IntegralTypedArrayBase<int>::set; inline PassRefPtr<Int32Array> subarray(int start) const; inline PassRefPtr<Int32Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/Int8Array.h b/Source/WTF/wtf/Int8Array.h index bb3e37e35..b29d2d9aa 100644 --- a/Source/WTF/wtf/Int8Array.h +++ b/Source/WTF/wtf/Int8Array.h @@ -43,9 +43,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Int8Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<signed char>* array, unsigned offset) { return TypedArrayBase<signed char>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<signed char>::set(index, value); } + using TypedArrayBase<signed char>::set; + using IntegralTypedArrayBase<signed char>::set; inline PassRefPtr<Int8Array> subarray(int start) const; inline PassRefPtr<Int8Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/IntegralTypedArrayBase.h b/Source/WTF/wtf/IntegralTypedArrayBase.h index 23dbdde5d..1faf14cab 100644 --- a/Source/WTF/wtf/IntegralTypedArrayBase.h +++ b/Source/WTF/wtf/IntegralTypedArrayBase.h @@ -43,7 +43,7 @@ class IntegralTypedArrayBase : public TypedArrayBase<T> { { if (index >= TypedArrayBase<T>::m_length) return; - if (isnan(value)) // Clamp NaN to 0 + if (std::isnan(value)) // Clamp NaN to 0 value = 0; // The double cast is necessary to get the correct wrapping // for out-of-range values with Int32Array and Uint32Array. diff --git a/Source/WTF/wtf/ListHashSet.h b/Source/WTF/wtf/ListHashSet.h index 8feef72b3..78639b406 100644 --- a/Source/WTF/wtf/ListHashSet.h +++ b/Source/WTF/wtf/ListHashSet.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> * * This library is free software; you can redistribute it and/or @@ -38,10 +38,6 @@ namespace WTF { // guaranteed safe against mutation of the ListHashSet, except for // removal of the item currently pointed to by a given iterator. - // In theory it would be possible to add prepend, insertAfter - // and an append that moves the element to the end even if already present, - // but unclear yet if these are needed. - template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet; template<typename Value, size_t inlineCapacity, typename HashFunctions> @@ -98,8 +94,6 @@ namespace WTF { int capacity() const; bool isEmpty() const; - size_t sizeInBytes() const; - iterator begin(); iterator end(); const_iterator begin() const; @@ -112,6 +106,7 @@ namespace WTF { ValueType& first(); const ValueType& first() const; + void removeFirst(); ValueType& last(); const ValueType& last() const; @@ -134,6 +129,14 @@ namespace WTF { // and a bool that is true if an new entry was added. AddResult add(const ValueType&); + // Add the value to the end of the collection. If the value was already in + // the list, it is moved to the end. + AddResult appendOrMoveToLast(const ValueType&); + + // Add the value to the beginning of the collection. If the value was already in + // the list, it is moved to the beginning. + AddResult prependOrMoveToFirst(const ValueType&); + AddResult insertBefore(const ValueType& beforeValue, const ValueType& newValue); AddResult insertBefore(iterator, const ValueType&); @@ -142,8 +145,10 @@ namespace WTF { void clear(); private: + void unlink(Node*); void unlinkAndDelete(Node*); void appendNode(Node*); + void prependNode(Node*); void insertNodeBefore(Node* beforeNode, Node* newNode); void deleteAllNodes(); @@ -211,15 +216,14 @@ namespace WTF { fastFree(node); } + private: + Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); } + Node* pastPool() { return pool() + m_poolSize; } bool inPool(Node* node) { return node >= pool() && node < pastPool(); } - private: - Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); } - Node* pastPool() { return pool() + m_poolSize; } - Node* m_freeList; bool m_isDoneWithInitialFreeList; static const size_t m_poolSize = inlineCapacity; @@ -562,18 +566,6 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> - size_t ListHashSet<T, inlineCapacity, U>::sizeInBytes() const - { - size_t result = sizeof(*this) + sizeof(*m_allocator); - result += sizeof(typename ImplType::ValueType) * m_impl.capacity(); - for (Node* node = m_head; node; node = node->m_next) { - if (!m_allocator->inPool(node)) - result += sizeof(Node); - } - return result; - } - - template<typename T, size_t inlineCapacity, typename U> inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin() { return makeIterator(m_head); @@ -629,6 +621,14 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> + inline void ListHashSet<T, inlineCapacity, U>::removeFirst() + { + ASSERT(!isEmpty()); + m_impl.remove(m_head); + unlinkAndDelete(m_head); + } + + template<typename T, size_t inlineCapacity, typename U> inline const T& ListHashSet<T, inlineCapacity, U>::first() const { ASSERT(!isEmpty()); @@ -724,6 +724,28 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> + typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::appendOrMoveToLast(const ValueType &value) + { + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); + Node* node = *result.iterator; + if (!result.isNewEntry) + unlink(node); + appendNode(node); + return AddResult(makeIterator(*result.iterator), result.isNewEntry); + } + + template<typename T, size_t inlineCapacity, typename U> + typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::prependOrMoveToFirst(const ValueType &value) + { + typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); + Node* node = *result.iterator; + if (!result.isNewEntry) + unlink(node); + prependNode(node); + return AddResult(makeIterator(*result.iterator), result.isNewEntry); + } + + template<typename T, size_t inlineCapacity, typename U> typename ListHashSet<T, inlineCapacity, U>::AddResult ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue) { typename ImplType::AddResult result = m_impl.template add<BaseTranslator>(newValue, m_allocator.get()); @@ -763,7 +785,7 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node) + void ListHashSet<T, inlineCapacity, U>::unlink(Node* node) { if (!node->m_prev) { ASSERT(node == m_head); @@ -780,7 +802,12 @@ namespace WTF { ASSERT(node != m_tail); node->m_next->m_prev = node->m_prev; } + } + template<typename T, size_t inlineCapacity, typename U> + void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node) + { + unlink(node); node->destroy(m_allocator.get()); } @@ -802,6 +829,20 @@ namespace WTF { } template<typename T, size_t inlineCapacity, typename U> + void ListHashSet<T, inlineCapacity, U>::prependNode(Node* node) + { + node->m_prev = 0; + node->m_next = m_head; + + if (m_head) + m_head->m_prev = node; + else + m_tail = node; + + m_head = node; + } + + template<typename T, size_t inlineCapacity, typename U> void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode) { if (!beforeNode) diff --git a/Source/WTF/wtf/ListRefPtr.h b/Source/WTF/wtf/ListRefPtr.h deleted file mode 100644 index 4ba0632d7..000000000 --- a/Source/WTF/wtf/ListRefPtr.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_ListRefPtr_h -#define WTF_ListRefPtr_h - -#include <wtf/RefPtr.h> - -namespace WTF { - - // Specialized version of RefPtr desgined for use in singly-linked lists. - // Derefs the list iteratively to avoid recursive derefing that can overflow the stack. - template <typename T> class ListRefPtr : public RefPtr<T> { - public: - ListRefPtr() : RefPtr<T>() {} - ListRefPtr(T* ptr) : RefPtr<T>(ptr) {} - ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {} - // see comment in PassRefPtr.h for why this takes const reference - template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {} - - ~ListRefPtr() - { - RefPtr<T> reaper = this->release(); - while (reaper && reaper->hasOneRef()) - reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper - } - - ListRefPtr& operator=(T* optr) { RefPtr<T>::operator=(optr); return *this; } - ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; } - ListRefPtr& operator=(const PassRefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; } - template <typename U> ListRefPtr& operator=(const RefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; } - template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; } - }; - - template <typename T> inline T* getPtr(const ListRefPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::ListRefPtr; - -#endif // WTF_ListRefPtr_h diff --git a/Source/WTF/wtf/MD5.cpp b/Source/WTF/wtf/MD5.cpp index 07bbadd9f..7d0100d0e 100644 --- a/Source/WTF/wtf/MD5.cpp +++ b/Source/WTF/wtf/MD5.cpp @@ -58,44 +58,6 @@ namespace WTF { -#ifdef NDEBUG -static inline void testMD5() { } -#else -// MD5 test case. -static bool isTestMD5Done; - -static void expectMD5(CString input, CString expected) -{ - MD5 md5; - md5.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length()); - Vector<uint8_t, 16> digest; - md5.checksum(digest); - char* buf = 0; - CString actual = CString::newUninitialized(32, buf); - for (size_t i = 0; i < 16; i++) { - snprintf(buf, 3, "%02x", digest.at(i)); - buf += 2; - } - ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%lu] actual:%s expected:%s", input.data(), static_cast<unsigned long>(input.length()), actual.data(), expected.data()); -} - -static void testMD5() -{ - if (isTestMD5Done) - return; - isTestMD5Done = true; - - // MD5 Test suite from http://www.ietf.org/rfc/rfc1321.txt - expectMD5("", "d41d8cd98f00b204e9800998ecf8427e"); - expectMD5("a", "0cc175b9c0f1b6a831c399e269772661"); - expectMD5("abc", "900150983cd24fb0d6963f7d28e17f72"); - expectMD5("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); - expectMD5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); - expectMD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"); - expectMD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"); -} -#endif - // Note: this code is harmless on little-endian machines. static void reverseBytes(uint8_t* buf, unsigned longs) @@ -203,8 +165,6 @@ static void MD5Transform(uint32_t buf[4], const uint32_t in[16]) MD5::MD5() { - // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. - testMD5(); m_buf[0] = 0x67452301; m_buf[1] = 0xefcdab89; m_buf[2] = 0x98badcfe; diff --git a/Source/WTF/wtf/MainThread.cpp b/Source/WTF/wtf/MainThread.cpp index f8686aa31..aea8c366e 100644 --- a/Source/WTF/wtf/MainThread.cpp +++ b/Source/WTF/wtf/MainThread.cpp @@ -36,10 +36,6 @@ #include "Threading.h" #include <wtf/ThreadSpecific.h> -#if PLATFORM(CHROMIUM) -#error Chromium uses a different main thread implementation -#endif - namespace WTF { struct FunctionWithContext { @@ -120,6 +116,7 @@ void initializeMainThread() pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadOnce); } +#if !USE(WEB_THREAD) static void initializeMainThreadToProcessMainThreadOnce() { mainThreadFunctionQueueMutex(); @@ -130,6 +127,8 @@ void initializeMainThreadToProcessMainThread() { pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadToProcessMainThreadOnce); } +#endif // !USE(WEB_THREAD) + #endif // 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that. diff --git a/Source/WTF/wtf/MainThread.h b/Source/WTF/wtf/MainThread.h index 9a40ad4f0..962799186 100644 --- a/Source/WTF/wtf/MainThread.h +++ b/Source/WTF/wtf/MainThread.h @@ -51,6 +51,14 @@ WTF_EXPORT_PRIVATE void setMainThreadCallbacksPaused(bool paused); WTF_EXPORT_PRIVATE bool isMainThread(); +#if USE(WEB_THREAD) +WTF_EXPORT_PRIVATE bool isWebThread(); +WTF_EXPORT_PRIVATE bool isUIThread(); +#else +inline bool isWebThread() { return isMainThread(); } +inline bool isUIThread() { return isMainThread(); } +#endif // USE(WEB_THREAD) + void initializeGCThreads(); #if ENABLE(PARALLEL_GC) @@ -68,10 +76,12 @@ void scheduleDispatchFunctionsOnMainThread(); void dispatchFunctionsFromMainThread(); #if PLATFORM(MAC) +#if !USE(WEB_THREAD) // This version of initializeMainThread sets up the main thread as corresponding // to the process's main thread, and not necessarily the thread that calls this // function. It should only be used as a legacy aid for Mac WebKit. WTF_EXPORT_PRIVATE void initializeMainThreadToProcessMainThread(); +#endif // !USE(WEB_THREAD) void initializeMainThreadToProcessMainThreadPlatform(); #endif diff --git a/Source/WTF/wtf/MathExtras.h b/Source/WTF/wtf/MathExtras.h index 3b5025d35..ce72c4aed 100644 --- a/Source/WTF/wtf/MathExtras.h +++ b/Source/WTF/wtf/MathExtras.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,6 +48,11 @@ // namespace. For now, we include math.h since the QNX cmath header only imports its functions // into the standard namespace. #include <math.h> +// These macros from math.h conflict with the real functions in the std namespace. +#undef signbit +#undef isnan +#undef isinf +#undef isfinite #endif #ifndef M_PI @@ -85,20 +90,26 @@ inline double wtf_ceil(double x) { return copysign(ceil(x), x); } #if OS(SOLARIS) +namespace std { + #ifndef isfinite inline bool isfinite(double x) { return finite(x) && !isnand(x); } #endif -#ifndef isinf -inline bool isinf(double x) { return !finite(x) && !isnand(x); } -#endif #ifndef signbit inline bool signbit(double x) { return copysign(1.0, x) < 0; } #endif +#ifndef isinf +inline bool isinf(double x) { return !finite(x) && !isnand(x); } +#endif + +} // namespace std #endif #if OS(OPENBSD) +namespace std { + #ifndef isfinite inline bool isfinite(double x) { return finite(x); } #endif @@ -106,9 +117,11 @@ inline bool isfinite(double x) { return finite(x); } inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; } #endif +} // namespace std + #endif -#if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) +#if COMPILER(MSVC) // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. static double round(double num) @@ -138,17 +151,17 @@ inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } inline long long abs(long num) { return labs(num); } #endif -#if OS(ANDROID) || COMPILER(MSVC) -// ANDROID and MSVC's math.h does not currently supply log2 or log2f. +#if COMPILER(MSVC) +// MSVC's math.h does not currently supply log2 or log2f. inline double log2(double num) { - // This constant is roughly M_LN2, which is not provided by default on Windows and Android. + // This constant is roughly M_LN2, which is not provided by default on Windows. return log(num) / 0.693147180559945309417232121458176568; } inline float log2f(float num) { - // This constant is roughly M_LN2, which is not provided by default on Windows and Android. + // This constant is roughly M_LN2, which is not provided by default on Windows. return logf(num) / 0.693147180559945309417232121458176568f; } #endif @@ -159,18 +172,22 @@ inline float log2f(float num) inline long long abs(long long num) { return _abs64(num); } #endif +namespace std { + inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } inline bool isnan(double num) { return !!_isnan(num); } +inline bool isfinite(double x) { return _finite(x); } inline bool signbit(double num) { return _copysign(1.0, num) < 0; } +} // namespace std + inline double nextafter(double x, double y) { return _nextafter(x, y); } inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } inline double copysign(double x, double y) { return _copysign(x, y); } -inline int isfinite(double x) { return _finite(x); } // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. -inline double wtf_atan2(double x, double y) +extern "C" inline double wtf_atan2(double x, double y) { double posInf = std::numeric_limits<double>::infinity(); double negInf = -std::numeric_limits<double>::infinity(); @@ -193,10 +210,10 @@ inline double wtf_atan2(double x, double y) } // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x. -inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); } +extern "C" inline double wtf_fmod(double x, double y) { return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y); } // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1. -inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } +extern "C" inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } #define atan2(x, y) wtf_atan2(x, y) #define fmod(x, y) wtf_fmod(x, y) @@ -212,7 +229,7 @@ inline long int lrint(double flt) fistp intgr }; #else - ASSERT(isfinite(flt)); + ASSERT(std::isfinite(flt)); double rounded = round(flt); intgr = static_cast<int64_t>(rounded); // If the fractional part is exactly 0.5, we need to check whether @@ -294,6 +311,11 @@ inline bool isWithinIntRange(float x) return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max()); } +template<typename T> inline bool hasOneBitSet(T value) +{ + return !((value - 1) & value) && value; +} + template<typename T> inline bool hasZeroOrOneBitsSet(T value) { return !((value - 1) & value); @@ -304,6 +326,16 @@ template<typename T> inline bool hasTwoOrMoreBitsSet(T value) return !hasZeroOrOneBitsSet(value); } +template <typename T> inline unsigned getLSBSet(T value) +{ + unsigned result = 0; + + while (value >>= 1) + ++result; + + return result; +} + template<typename T> inline T timesThreePlusOneDividedByTwo(T value) { // Mathematically equivalent to: @@ -314,30 +346,15 @@ template<typename T> inline T timesThreePlusOneDividedByTwo(T value) return value + (value >> 1) + (value & 1); } -#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(SOLARIS) -using std::isfinite; -#if !COMPILER_QUIRK(GCC11_GLOBAL_ISINF_ISNAN) -using std::isinf; -using std::isnan; -#endif -using std::signbit; -#endif - -#if COMPILER_QUIRK(GCC11_GLOBAL_ISINF_ISNAN) -// A workaround to avoid conflicting declarations of isinf and isnan when compiling with GCC in C++11 mode. -namespace std { - inline bool wtf_isinf(float f) { return std::isinf(f); } - inline bool wtf_isinf(double d) { return std::isinf(d); } - inline bool wtf_isnan(float f) { return std::isnan(f); } - inline bool wtf_isnan(double d) { return std::isnan(d); } -}; - -using std::wtf_isinf; -using std::wtf_isnan; +template<typename T> inline bool isNotZeroAndOrdered(T value) +{ + return value > 0.0 || value < 0.0; +} -#define isinf(x) wtf_isinf(x) -#define isnan(x) wtf_isnan(x) -#endif +template<typename T> inline bool isZeroOrUnordered(T value) +{ + return !isNotZeroAndOrdered(value); +} #ifndef UINT64_C #if COMPILER(MSVC) @@ -352,7 +369,7 @@ inline double wtf_pow(double x, double y) { // MinGW-w64 has a custom implementation for pow. // This handles certain special cases that are different. - if ((x == 0.0 || isinf(x)) && isfinite(y)) { + if ((x == 0.0 || std::isinf(x)) && std::isfinite(y)) { double f; if (modf(y, &f) != 0.0) return ((x == 0.0) ^ (y > 0.0)) ? std::numeric_limits<double>::infinity() : 0.0; @@ -375,9 +392,9 @@ inline double wtf_pow(double x, double y) // (sign ? -1 : 1) * pow(2, exponent) * (mantissa / (1 << 52)) inline void decomposeDouble(double number, bool& sign, int32_t& exponent, uint64_t& mantissa) { - ASSERT(isfinite(number)); + ASSERT(std::isfinite(number)); - sign = signbit(number); + sign = std::signbit(number); uint64_t bits = WTF::bitwise_cast<uint64_t>(number); exponent = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff; @@ -394,7 +411,7 @@ inline void decomposeDouble(double number, bool& sign, int32_t& exponent, uint64 // Calculate d % 2^{64}. inline void doubleToInteger(double d, unsigned long long& value) { - if (isnan(d) || isinf(d)) + if (std::isnan(d) || std::isinf(d)) value = 0; else { // -2^{64} < fmodValue < 2^{64}. @@ -414,4 +431,39 @@ inline void doubleToInteger(double d, unsigned long long& value) } } +namespace WTF { + +// From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +inline uint32_t roundUpToPowerOfTwo(uint32_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +inline unsigned fastLog2(unsigned i) +{ + unsigned log2 = 0; + if (i & (i - 1)) + log2 += 1; + if (i >> 16) + log2 += 16, i >>= 16; + if (i >> 8) + log2 += 8, i >>= 8; + if (i >> 4) + log2 += 4, i >>= 4; + if (i >> 2) + log2 += 2, i >>= 2; + if (i >> 1) + log2 += 1; + return log2; +} + +} // namespace WTF + #endif // #ifndef WTF_MathExtras_h diff --git a/Source/WTF/wtf/MediaTime.cpp b/Source/WTF/wtf/MediaTime.cpp index 6eb2bb09b..4b2eee84c 100644 --- a/Source/WTF/wtf/MediaTime.cpp +++ b/Source/WTF/wtf/MediaTime.cpp @@ -83,8 +83,8 @@ MediaTime MediaTime::createWithFloat(float floatTime, int32_t timeScale) { if (floatTime != floatTime) return invalidTime(); - if (isinf(floatTime)) - return signbit(floatTime) ? negativeInfiniteTime() : positiveInfiniteTime(); + if (std::isinf(floatTime)) + return std::signbit(floatTime) ? negativeInfiniteTime() : positiveInfiniteTime(); if (floatTime > numeric_limits<int64_t>::max()) return positiveInfiniteTime(); if (floatTime < numeric_limits<int64_t>::min()) @@ -99,8 +99,8 @@ MediaTime MediaTime::createWithDouble(double doubleTime, int32_t timeScale) { if (doubleTime != doubleTime) return invalidTime(); - if (isinf(doubleTime)) - return signbit(doubleTime) ? negativeInfiniteTime() : positiveInfiniteTime(); + if (std::isinf(doubleTime)) + return std::signbit(doubleTime) ? negativeInfiniteTime() : positiveInfiniteTime(); if (doubleTime > numeric_limits<int64_t>::max()) return positiveInfiniteTime(); if (doubleTime < numeric_limits<int64_t>::min()) diff --git a/Source/WTF/wtf/MediaTime.h b/Source/WTF/wtf/MediaTime.h index 413b1a73c..413b1a73c 100755..100644 --- a/Source/WTF/wtf/MediaTime.h +++ b/Source/WTF/wtf/MediaTime.h diff --git a/Source/WTF/wtf/MemoryInstrumentation.cpp b/Source/WTF/wtf/MemoryInstrumentation.cpp deleted file mode 100644 index d4be2b6dc..000000000 --- a/Source/WTF/wtf/MemoryInstrumentation.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2012 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 "MemoryInstrumentation.h" - -#include <wtf/MemoryObjectInfo.h> - -#if DEBUG_POINTER_INSTRUMENTATION -#include <stdio.h> -#include <wtf/Assertions.h> -#endif - -namespace WTF { - -MemoryInstrumentation::MemoryInstrumentation(MemoryInstrumentationClient* client) - : m_client(client) - , m_rootObjectInfo(adoptPtr(new MemoryObjectInfo(this, 0))) -{ -} - -MemoryInstrumentation::~MemoryInstrumentation() -{ -} - -MemoryObjectType MemoryInstrumentation::getObjectType(MemoryObjectInfo* objectInfo) -{ - return objectInfo->objectType(); -} - -void MemoryInstrumentation::callReportObjectInfo(MemoryObjectInfo* memoryObjectInfo, const void* pointer, MemoryObjectType objectType, size_t objectSize) -{ - memoryObjectInfo->reportObjectInfo(pointer, objectType, objectSize); -} - -MemoryInstrumentation::InstrumentedPointerBase::InstrumentedPointerBase(MemoryObjectInfo* memoryObjectInfo) - : m_ownerObjectType(memoryObjectInfo->objectType()) -{ -#if DEBUG_POINTER_INSTRUMENTATION - m_callStackSize = s_maxCallStackSize; - WTFGetBacktrace(m_callStack, &m_callStackSize); -#endif -} - -void MemoryInstrumentation::InstrumentedPointerBase::process(MemoryInstrumentation* memoryInstrumentation) -{ - MemoryObjectInfo memoryObjectInfo(memoryInstrumentation, m_ownerObjectType); - const void* originalPointer = callReportMemoryUsage(&memoryObjectInfo); - - const void* pointer = memoryObjectInfo.reportedPointer(); - ASSERT(pointer); - if (pointer != originalPointer && memoryInstrumentation->visited(pointer)) - return; - memoryInstrumentation->countObjectSize(pointer, memoryObjectInfo.objectType(), memoryObjectInfo.objectSize()); - if (!memoryInstrumentation->checkCountedObject(pointer)) { -#if DEBUG_POINTER_INSTRUMENTATION - fputs("Unknown object counted:\n", stderr); - WTFPrintBacktrace(m_callStack, m_callStackSize); -#endif - } -} - -void MemoryClassInfo::init(const void* pointer, MemoryObjectType objectType, size_t actualSize) -{ - m_memoryObjectInfo->reportObjectInfo(pointer, objectType, actualSize); - m_memoryInstrumentation = m_memoryObjectInfo->memoryInstrumentation(); - m_objectType = m_memoryObjectInfo->objectType(); -} - -void MemoryClassInfo::addRawBuffer(const void* const& buffer, size_t size) -{ - m_memoryInstrumentation->addRawBuffer(buffer, m_objectType, size); -} - -void MemoryClassInfo::addPrivateBuffer(size_t size, MemoryObjectType ownerObjectType) -{ - if (!size) - return; - if (!ownerObjectType) - ownerObjectType = m_objectType; - m_memoryInstrumentation->countObjectSize(0, ownerObjectType, size); -} - -} // namespace WTF diff --git a/Source/WTF/wtf/MemoryInstrumentation.h b/Source/WTF/wtf/MemoryInstrumentation.h deleted file mode 100644 index 2a6832b71..000000000 --- a/Source/WTF/wtf/MemoryInstrumentation.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentation_h -#define MemoryInstrumentation_h - -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/RefPtr.h> - -#define DEBUG_POINTER_INSTRUMENTATION 0 - -namespace WTF { - -class MemoryClassInfo; -class MemoryObjectInfo; -class MemoryInstrumentation; - -typedef const char* MemoryObjectType; - -enum MemoryOwningType { - byPointer, - byReference -}; - -template<typename T> void reportMemoryUsage(const T* const&, MemoryObjectInfo*); - -class MemoryInstrumentationClient { -public: - virtual ~MemoryInstrumentationClient() { } - virtual void countObjectSize(const void*, MemoryObjectType, size_t) = 0; - virtual bool visited(const void*) = 0; - virtual bool checkCountedObject(const void*) = 0; -}; - -class MemoryInstrumentation { -public: - WTF_EXPORT_PRIVATE explicit MemoryInstrumentation(MemoryInstrumentationClient*); - WTF_EXPORT_PRIVATE virtual ~MemoryInstrumentation(); - - template <typename T> void addRootObject(const T& t) - { - addObject(t, m_rootObjectInfo.get()); - processDeferredInstrumentedPointers(); - } - -protected: - class InstrumentedPointerBase { - public: - WTF_EXPORT_PRIVATE explicit InstrumentedPointerBase(MemoryObjectInfo*); - virtual ~InstrumentedPointerBase() { } - WTF_EXPORT_PRIVATE void process(MemoryInstrumentation*); - - protected: - virtual const void* callReportMemoryUsage(MemoryObjectInfo*) = 0; - - private: - const MemoryObjectType m_ownerObjectType; -#if DEBUG_POINTER_INSTRUMENTATION - static const int s_maxCallStackSize = 32; - void* m_callStack[s_maxCallStackSize]; - int m_callStackSize; -#endif - }; - -private: - void countObjectSize(const void* object, MemoryObjectType objectType, size_t size) { m_client->countObjectSize(object, objectType, size); } - bool visited(const void* pointer) { return m_client->visited(pointer); } - bool checkCountedObject(const void* pointer) { return m_client->checkCountedObject(pointer); } - - virtual void deferInstrumentedPointer(PassOwnPtr<InstrumentedPointerBase>) = 0; - virtual void processDeferredInstrumentedPointers() = 0; - - WTF_EXPORT_PRIVATE static MemoryObjectType getObjectType(MemoryObjectInfo*); - - friend class MemoryClassInfo; - template<typename T> friend void reportMemoryUsage(const T* const&, MemoryObjectInfo*); - - template<typename T> static void selectInstrumentationMethod(const T* const& object, MemoryObjectInfo* memoryObjectInfo) - { - // If there is reportMemoryUsage method on the object, call it. - // Otherwise count only object's self size. - reportObjectMemoryUsage<T, void (T::*)(MemoryObjectInfo*) const>(object, memoryObjectInfo, 0); - } - - template<typename Type, Type Ptr> struct MemberHelperStruct; - template<typename T, typename Type> - static void reportObjectMemoryUsage(const T* const& object, MemoryObjectInfo* memoryObjectInfo, MemberHelperStruct<Type, &T::reportMemoryUsage>*) - { - object->reportMemoryUsage(memoryObjectInfo); - } - - template<typename T, typename Type> - static void reportObjectMemoryUsage(const T* const& object, MemoryObjectInfo* memoryObjectInfo, ...) - { - callReportObjectInfo(memoryObjectInfo, object, 0, sizeof(T)); - } - WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const void* pointer, MemoryObjectType, size_t objectSize); - - template<typename T> class InstrumentedPointer : public InstrumentedPointerBase { - public: - InstrumentedPointer(const T* pointer, MemoryObjectInfo* ownerObjectInfo); - - protected: - virtual const void* callReportMemoryUsage(MemoryObjectInfo*) OVERRIDE; - - private: - const T* m_pointer; - }; - - template<typename T> void addObject(const T& t, MemoryObjectInfo* ownerObjectInfo) { OwningTraits<T>::addObject(this, t, ownerObjectInfo); } - void addRawBuffer(const void* const& buffer, MemoryObjectType ownerObjectType, size_t size) - { - if (!buffer || visited(buffer)) - return; - countObjectSize(buffer, ownerObjectType, size); - } - - template<typename T> - struct OwningTraits { // Default byReference implementation. - static void addObject(MemoryInstrumentation* instrumentation, const T& t, MemoryObjectInfo* ownerObjectInfo) - { - instrumentation->addObjectImpl(&t, ownerObjectInfo, byReference); - } - }; - - template<typename T> - struct OwningTraits<T*> { // Custom byPointer implementation. - static void addObject(MemoryInstrumentation* instrumentation, const T* const& t, MemoryObjectInfo* ownerObjectInfo) - { - instrumentation->addObjectImpl(t, ownerObjectInfo, byPointer); - } - }; - - template<typename T> void addObjectImpl(const T* const&, MemoryObjectInfo*, MemoryOwningType); - template<typename T> void addObjectImpl(const OwnPtr<T>* const&, MemoryObjectInfo*, MemoryOwningType); - template<typename T> void addObjectImpl(const RefPtr<T>* const&, MemoryObjectInfo*, MemoryOwningType); - - MemoryInstrumentationClient* m_client; - OwnPtr<MemoryObjectInfo> m_rootObjectInfo; -}; - -class MemoryClassInfo { -public: - template<typename T> - MemoryClassInfo(MemoryObjectInfo* memoryObjectInfo, const T* pointer, MemoryObjectType objectType = 0, size_t actualSize = sizeof(T)) - : m_memoryObjectInfo(memoryObjectInfo) - , m_memoryInstrumentation(0) - , m_objectType(0) - { - init(pointer, objectType, actualSize); - } - - template<typename M> void addMember(const M& member) { m_memoryInstrumentation->addObject(member, m_memoryObjectInfo); } - WTF_EXPORT_PRIVATE void addRawBuffer(const void* const& buffer, size_t); - WTF_EXPORT_PRIVATE void addPrivateBuffer(size_t, MemoryObjectType ownerObjectType = 0); - - void addWeakPointer(void*) { } - -private: - WTF_EXPORT_PRIVATE void init(const void* pointer, MemoryObjectType, size_t actualSize); - - MemoryObjectInfo* m_memoryObjectInfo; - MemoryInstrumentation* m_memoryInstrumentation; - MemoryObjectType m_objectType; -}; - -template<typename T> -void reportMemoryUsage(const T* const& object, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryInstrumentation::selectInstrumentationMethod<T>(object, memoryObjectInfo); -} - -template<typename T> -void MemoryInstrumentation::addObjectImpl(const T* const& object, MemoryObjectInfo* ownerObjectInfo, MemoryOwningType owningType) -{ - if (owningType == byReference) - reportMemoryUsage(object, ownerObjectInfo); - else { - if (!object || visited(object)) - return; - deferInstrumentedPointer(adoptPtr(new InstrumentedPointer<T>(object, ownerObjectInfo))); - } -} - -template<typename T> -void MemoryInstrumentation::addObjectImpl(const OwnPtr<T>* const& object, MemoryObjectInfo* ownerObjectInfo, MemoryOwningType owningType) -{ - if (owningType == byPointer && !visited(object)) - countObjectSize(object, getObjectType(ownerObjectInfo), sizeof(*object)); - addObjectImpl(object->get(), ownerObjectInfo, byPointer); -} - -template<typename T> -void MemoryInstrumentation::addObjectImpl(const RefPtr<T>* const& object, MemoryObjectInfo* ownerObjectInfo, MemoryOwningType owningType) -{ - if (owningType == byPointer && !visited(object)) - countObjectSize(object, getObjectType(ownerObjectInfo), sizeof(*object)); - addObjectImpl(object->get(), ownerObjectInfo, byPointer); -} - -template<typename T> -MemoryInstrumentation::InstrumentedPointer<T>::InstrumentedPointer(const T* pointer, MemoryObjectInfo* ownerObjectInfo) - : InstrumentedPointerBase(ownerObjectInfo) - , m_pointer(pointer) -{ -} - -template<typename T> -const void* MemoryInstrumentation::InstrumentedPointer<T>::callReportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) -{ - reportMemoryUsage(m_pointer, memoryObjectInfo); - return m_pointer; -} - -// Link time guard for classes with external memory instrumentation. -template<typename T, size_t inlineCapacity> class Vector; -template<typename T, size_t inlineCapacity> void reportMemoryUsage(const Vector<T, inlineCapacity>* const&, MemoryObjectInfo*); - -template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> class HashMap; -template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> void reportMemoryUsage(const HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>* const&, MemoryObjectInfo*); - -template<typename ValueArg, typename HashArg, typename TraitsArg> class HashCountedSet; -template<typename ValueArg, typename HashArg, typename TraitsArg> void reportMemoryUsage(const HashCountedSet<ValueArg, HashArg, TraitsArg>* const&, MemoryObjectInfo*); - -template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSet; -template<typename ValueArg, size_t inlineCapacity, typename HashArg> void reportMemoryUsage(const ListHashSet<ValueArg, inlineCapacity, HashArg>* const&, MemoryObjectInfo*); - -class String; -void reportMemoryUsage(const String* const&, MemoryObjectInfo*); - -class StringImpl; -void reportMemoryUsage(const StringImpl* const&, MemoryObjectInfo*); - -class AtomicString; -void reportMemoryUsage(const AtomicString* const&, MemoryObjectInfo*); - -class CString; -void reportMemoryUsage(const CString* const&, MemoryObjectInfo*); - -class CStringBuffer; -void reportMemoryUsage(const CStringBuffer* const&, MemoryObjectInfo*); - -class ParsedURL; -void reportMemoryUsage(const ParsedURL* const&, MemoryObjectInfo*); - -class URLString; -void reportMemoryUsage(const URLString* const&, MemoryObjectInfo*); - -} // namespace WTF - -#endif // !defined(MemoryInstrumentation_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationArrayBufferView.h b/Source/WTF/wtf/MemoryInstrumentationArrayBufferView.h deleted file mode 100644 index 006f45194..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationArrayBufferView.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationArrayBufferView_h -#define MemoryInstrumentationArrayBufferView_h - -#include <wtf/ArrayBufferView.h> -#include <wtf/MemoryInstrumentation.h> - -namespace WTF { - -inline void reportMemoryUsage(const ArrayBufferView* const& arrayBufferView, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, arrayBufferView); - info.addMember(arrayBufferView->buffer().get()); -} - -inline void reportMemoryUsage(const ArrayBuffer* const& arrayBuffer, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, arrayBuffer); - info.addRawBuffer(arrayBuffer->data(), arrayBuffer->byteLength()); -} - -} - -#endif // !defined(MemoryInstrumentationArrayBufferView_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationHashCountedSet.h b/Source/WTF/wtf/MemoryInstrumentationHashCountedSet.h deleted file mode 100644 index 623840160..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationHashCountedSet.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationHashCountedSet_h -#define MemoryInstrumentationHashCountedSet_h - -#include <wtf/HashCountedSet.h> -#include <wtf/MemoryInstrumentationSequence.h> - -namespace WTF { - -template<typename ValueArg, typename HashArg, typename TraitsArg> -void reportMemoryUsage(const HashCountedSet<ValueArg, HashArg, TraitsArg>* const& hashSet, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, hashSet); - - typedef HashMap<ValueArg, unsigned, HashArg, TraitsArg> HashMapType; - info.addPrivateBuffer(sizeof(typename HashMapType::ValueType) * hashSet->capacity()); - reportSequenceMemoryUsage<ValueArg, typename HashMapType::const_iterator::Keys>(hashSet->begin().keys(), hashSet->end().keys(), info); -} - -} - -#endif // !defined(MemoryInstrumentationHashCountedSet_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationHashMap.h b/Source/WTF/wtf/MemoryInstrumentationHashMap.h deleted file mode 100644 index 699c4eb2f..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationHashMap.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationHashMap_h -#define MemoryInstrumentationHashMap_h - -#include <wtf/HashMap.h> -#include <wtf/MemoryInstrumentationSequence.h> - -namespace WTF { - -template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> -void reportMemoryUsage(const HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>* const& hashMap, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, hashMap); - typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> HashMapType; - info.addPrivateBuffer(sizeof(typename HashMapType::ValueType) * hashMap->capacity()); - - reportSequenceMemoryUsage<KeyArg, typename HashMapType::const_iterator::Keys>(hashMap->begin().keys(), hashMap->end().keys(), info); - reportSequenceMemoryUsage<MappedArg, typename HashMapType::const_iterator::Values>(hashMap->begin().values(), hashMap->end().values(), info); -} - -} - -#endif // !defined(MemoryInstrumentationHashMap_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationHashSet.h b/Source/WTF/wtf/MemoryInstrumentationHashSet.h deleted file mode 100644 index aa1567b11..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationHashSet.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationHashSet_h -#define MemoryInstrumentationHashSet_h - -#include <wtf/HashSet.h> -#include <wtf/MemoryInstrumentationSequence.h> - -namespace WTF { - -template<typename ValueArg, typename HashArg, typename TraitsArg> -void reportMemoryUsage(const HashSet<ValueArg, HashArg, TraitsArg>* const& hashSet, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, hashSet); - info.addPrivateBuffer(sizeof(typename HashTable<ValueArg, ValueArg, IdentityExtractor, HashArg, TraitsArg, TraitsArg>::ValueType) * hashSet->capacity()); - reportSequenceMemoryUsage<ValueArg, typename HashSet<ValueArg, HashArg, TraitsArg>::const_iterator>(hashSet->begin(), hashSet->end(), info); -} - -} - -#endif // !defined(MemoryInstrumentationHashSet_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationListHashSet.h b/Source/WTF/wtf/MemoryInstrumentationListHashSet.h deleted file mode 100644 index 0e31c569b..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationListHashSet.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationListHashSet_h -#define MemoryInstrumentationListHashSet_h - -#include <wtf/ListHashSet.h> -#include <wtf/MemoryInstrumentationSequence.h> - -namespace WTF { - -template<typename ValueArg, size_t inlineCapacity, typename HashArg> -void reportMemoryUsage(const ListHashSet<ValueArg, inlineCapacity, HashArg>* const& set, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, set); - info.addPrivateBuffer(set->sizeInBytes() - sizeof(*set)); - reportSequenceMemoryUsage<ValueArg, typename ListHashSet<ValueArg, inlineCapacity, HashArg>::const_iterator>(set->begin(), set->end(), info); -} - -} - -#endif // !defined(MemoryInstrumentationListHashSet_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationParsedURL.h b/Source/WTF/wtf/MemoryInstrumentationParsedURL.h deleted file mode 100644 index c1f497228..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationParsedURL.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationParsedURL_h -#define MemoryInstrumentationParsedURL_h - -#include <wtf/MemoryInstrumentation.h> -#include <wtf/MemoryInstrumentationString.h> -#include <wtf/url/api/ParsedURL.h> - -namespace WTF { - -inline void reportMemoryUsage(const URLString* const& urlString, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, urlString); - info.addMember(urlString->string()); -} - -inline void reportMemoryUsage(const ParsedURL* const& parsedURL, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, parsedURL); - info.addMember(parsedURL->spec()); -} - -} - -#endif // !defined(MemoryInstrumentationiParsedURL_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationSequence.h b/Source/WTF/wtf/MemoryInstrumentationSequence.h deleted file mode 100644 index bbf204c47..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationSequence.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationSequence_h -#define MemoryInstrumentationSequence_h - -#include <wtf/MemoryInstrumentation.h> -#include <wtf/TypeTraits.h> - -namespace WTF { - -template<typename ValueType> -struct SequenceMemoryInstrumentationTraits { - template <typename I> static void reportMemoryUsage(I iterator, I end, MemoryClassInfo& info) - { - while (iterator != end) { - info.addMember(*iterator); - ++iterator; - } - } -}; - -template<> struct SequenceMemoryInstrumentationTraits<int> { - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } -}; - -template<> struct SequenceMemoryInstrumentationTraits<void*> { - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } -}; - -template<> struct SequenceMemoryInstrumentationTraits<char*> { - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } -}; - -template<> struct SequenceMemoryInstrumentationTraits<const char*> { - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } -}; - -template<> struct SequenceMemoryInstrumentationTraits<const void*> { - template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } -}; - -template<typename ValueType, typename I> void reportSequenceMemoryUsage(I begin, I end, MemoryClassInfo& info) -{ - // Check if type is convertible to integer to handle iteration through enum values. - SequenceMemoryInstrumentationTraits<typename Conditional<IsConvertibleToInteger<ValueType>::value, int, ValueType>::Type>::reportMemoryUsage(begin, end, info); -} - -} - -#endif // !defined(MemoryInstrumentationSequence_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationString.h b/Source/WTF/wtf/MemoryInstrumentationString.h deleted file mode 100644 index 6e8800f21..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationString.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationString_h -#define MemoryInstrumentationString_h - -#include <wtf/MemoryInstrumentation.h> -#include <wtf/text/AtomicString.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuilder.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -inline void reportMemoryUsage(const StringImpl* const& stringImpl, MemoryObjectInfo* memoryObjectInfo) -{ - size_t selfSize = sizeof(StringImpl); - - size_t length = stringImpl->length() + (stringImpl->hasTerminatingNullCharacter() ? 1 : 0); - size_t bufferSize = length * (stringImpl->is8Bit() ? sizeof(LChar) : sizeof(UChar)); - const void* buffer = stringImpl->is8Bit() ? static_cast<const void*>(stringImpl->characters8()) : static_cast<const void*>(stringImpl->characters16()); - - // Count size used by internal buffer but skip strings that were constructed from literals. - if (stringImpl->hasInternalBuffer() && buffer == stringImpl + 1) - selfSize += bufferSize; - - MemoryClassInfo info(memoryObjectInfo, stringImpl, 0, selfSize); - - if (StringImpl* baseString = stringImpl->baseString()) - info.addMember(baseString); - else { - if (stringImpl->hasOwnedBuffer()) - info.addRawBuffer(buffer, bufferSize); - - if (stringImpl->has16BitShadow()) - info.addRawBuffer(stringImpl->characters(), length * sizeof(UChar)); - } -} - -inline void reportMemoryUsage(const String* const& string, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, string); - info.addMember(string->impl()); -} - -inline void reportMemoryUsage(const AtomicString* const& atomicString, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, atomicString); - info.addMember(atomicString->string()); -} - -inline void reportMemoryUsage(const CStringBuffer* const& cStringBuffer, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, cStringBuffer, 0, sizeof(*cStringBuffer) + cStringBuffer->length()); -} - -inline void reportMemoryUsage(const CString* const& cString, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, cString); - info.addMember(cString->buffer()); -} - -} - -#endif // !defined(MemoryInstrumentationVector_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationVector.h b/Source/WTF/wtf/MemoryInstrumentationVector.h deleted file mode 100644 index 406b98361..000000000 --- a/Source/WTF/wtf/MemoryInstrumentationVector.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryInstrumentationVector_h -#define MemoryInstrumentationVector_h - -#include <wtf/MemoryInstrumentationSequence.h> -#include <wtf/Vector.h> - -namespace WTF { - -template<typename T, size_t inlineCapacity> -void reportMemoryUsage(const Vector<T, inlineCapacity>* const& vector, MemoryObjectInfo* memoryObjectInfo) -{ - MemoryClassInfo info(memoryObjectInfo, vector); - if (inlineCapacity < vector->capacity()) - info.addRawBuffer(vector->data(), vector->capacity() * sizeof(T)); - reportSequenceMemoryUsage<T, typename Vector<T, inlineCapacity>::const_iterator>(vector->begin(), vector->end(), info); -} - -} - -#endif // !defined(MemoryInstrumentationVector_h) diff --git a/Source/WTF/wtf/MemoryObjectInfo.h b/Source/WTF/wtf/MemoryObjectInfo.h deleted file mode 100644 index 1c7fe6c83..000000000 --- a/Source/WTF/wtf/MemoryObjectInfo.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2012 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 MemoryObjectInfo_h -#define MemoryObjectInfo_h - -namespace WTF { - -class MemoryClassInfo; -class MemoryInstrumentation; - -typedef const char* MemoryObjectType; - -class MemoryObjectInfo { -public: - MemoryObjectInfo(MemoryInstrumentation* memoryInstrumentation, MemoryObjectType ownerObjectType) - : m_memoryInstrumentation(memoryInstrumentation) - , m_objectType(ownerObjectType) - , m_objectSize(0) - , m_pointer(0) - { } - - typedef MemoryClassInfo ClassInfo; - - MemoryObjectType objectType() const { return m_objectType; } - size_t objectSize() const { return m_objectSize; } - const void* reportedPointer() const { return m_pointer; } - - MemoryInstrumentation* memoryInstrumentation() { return m_memoryInstrumentation; } - -private: - friend class MemoryClassInfo; - friend class MemoryInstrumentation; - - void reportObjectInfo(const void* pointer, MemoryObjectType objectType, size_t objectSize) - { - if (!m_objectSize) { - m_pointer = pointer; - m_objectSize = objectSize; - if (objectType) - m_objectType = objectType; - } - } - - MemoryInstrumentation* m_memoryInstrumentation; - MemoryObjectType m_objectType; - size_t m_objectSize; - const void* m_pointer; -}; - -} // namespace WTF - -#endif // !defined(MemoryObjectInfo_h) diff --git a/Source/WTF/wtf/MessageQueue.h b/Source/WTF/wtf/MessageQueue.h index dda852fe1..4f19aed50 100644 --- a/Source/WTF/wtf/MessageQueue.h +++ b/Source/WTF/wtf/MessageQueue.h @@ -55,6 +55,7 @@ namespace WTF { ~MessageQueue(); void append(PassOwnPtr<DataType>); + void appendAndKill(PassOwnPtr<DataType>); bool appendAndCheckEmpty(PassOwnPtr<DataType>); void prepend(PassOwnPtr<DataType>); @@ -98,6 +99,15 @@ namespace WTF { m_condition.signal(); } + template<typename DataType> + inline void MessageQueue<DataType>::appendAndKill(PassOwnPtr<DataType> message) + { + MutexLocker lock(m_mutex); + m_queue.append(message.leakPtr()); + m_killed = true; + m_condition.broadcast(); + } + // Returns true if the queue was empty before the item was added. template<typename DataType> inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message) diff --git a/Source/WTF/wtf/MetaAllocator.cpp b/Source/WTF/wtf/MetaAllocator.cpp index 068acea0a..d206233b6 100644 --- a/Source/WTF/wtf/MetaAllocator.cpp +++ b/Source/WTF/wtf/MetaAllocator.cpp @@ -31,6 +31,7 @@ #include <wtf/DataLog.h> #include <wtf/FastMalloc.h> +#include <wtf/ProcessID.h> namespace WTF { @@ -113,9 +114,9 @@ void MetaAllocatorHandle::shrink(size_t newSizeInBytes) m_sizeInBytes = newSizeInBytes; } -MetaAllocator::MetaAllocator(size_t allocationGranule) +MetaAllocator::MetaAllocator(size_t allocationGranule, size_t pageSize) : m_allocationGranule(allocationGranule) - , m_pageSize(pageSize()) + , m_pageSize(pageSize) , m_bytesAllocated(0) , m_bytesReserved(0) , m_bytesCommitted(0) @@ -449,8 +450,9 @@ void MetaAllocator::freeFreeSpaceNode(FreeSpaceNode* node) #if ENABLE(META_ALLOCATOR_PROFILE) void MetaAllocator::dumpProfile() { - dataLogF("%d: MetaAllocator(%p): num allocations = %u, num frees = %u, allocated = %lu, reserved = %lu, committed = %lu\n", - getpid(), this, m_numAllocations, m_numFrees, m_bytesAllocated, m_bytesReserved, m_bytesCommitted); + dataLogF( + "%d: MetaAllocator(%p): num allocations = %u, num frees = %u, allocated = %lu, reserved = %lu, committed = %lu\n", + getCurrentProcessID(), this, m_numAllocations, m_numFrees, m_bytesAllocated, m_bytesReserved, m_bytesCommitted); } #endif diff --git a/Source/WTF/wtf/MetaAllocator.h b/Source/WTF/wtf/MetaAllocator.h index ece6412ab..0adc93bb4 100644 --- a/Source/WTF/wtf/MetaAllocator.h +++ b/Source/WTF/wtf/MetaAllocator.h @@ -64,7 +64,7 @@ class MetaAllocator { WTF_MAKE_NONCOPYABLE(MetaAllocator); public: - WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule); + WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule, size_t pageSize = WTF::pageSize()); WTF_EXPORT_PRIVATE virtual ~MetaAllocator(); diff --git a/Source/WTF/wtf/NeverDestroyed.h b/Source/WTF/wtf/NeverDestroyed.h new file mode 100644 index 000000000..24819453b --- /dev/null +++ b/Source/WTF/wtf/NeverDestroyed.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NeverDestroyed_h +#define NeverDestroyed_h + +#include <wtf/Alignment.h> +#include <wtf/Noncopyable.h> +#include <wtf/StdLibExtras.h> +#include <wtf/TypeTraits.h> + +// NeverDestroyed is a smart pointer like class who ensures that the destructor +// for the given object is never called, but doesn't use the heap to allocate it. +// It's useful for static local variables, and can be used like so: +// +// MySharedGlobal& mySharedGlobal() +// { +// static NeverDestroyed<MySharedGlobal> myGlobal("Hello", 42); +// return myGlobal; +// } +// + +namespace WTF { + +template<typename T> class NeverDestroyed { + WTF_MAKE_NONCOPYABLE(NeverDestroyed); + +public: +#if COMPILER_SUPPORTS(CXX_VARIADIC_TEMPLATES) + template<typename... Args> + NeverDestroyed(Args&&... args) + { + new (asPtr()) T(std::forward<Args>(args)...); + } +#else + NeverDestroyed() + { + new (NotNull, asPtr()) T; + } + + template<typename P1> + NeverDestroyed(const P1& p1) + { + new (NotNull, asPtr()) T(p1); + } +#endif + + operator T&() { return *asPtr(); } + +private: +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + NeverDestroyed(NeverDestroyed&&) WTF_DELETED_FUNCTION; + NeverDestroyed& operator=(NeverDestroyed&&) WTF_DELETED_FUNCTION; +#endif + + typedef typename WTF::RemoveConst<T>::Type *PointerType; + + PointerType asPtr() { return reinterpret_cast<PointerType>(&m_storage); } + + // FIXME: Investigate whether we should allocate a hunk of virtual memory + // and hand out chunks of it to NeverDestroyed instead, to reduce fragmentation. + AlignedBuffer<sizeof(T), WTF_ALIGN_OF(T)> m_storage; +}; + +} // namespace WTF; + +using WTF::NeverDestroyed; + +#endif // NeverDestroyed_h diff --git a/Source/WTF/wtf/Noncopyable.h b/Source/WTF/wtf/Noncopyable.h index f6bdfbb40..c64cf63c2 100644 --- a/Source/WTF/wtf/Noncopyable.h +++ b/Source/WTF/wtf/Noncopyable.h @@ -23,16 +23,9 @@ #include <wtf/Compiler.h> -#if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) - #define WTF_MAKE_NONCOPYABLE(ClassName) \ - private: \ - ClassName(const ClassName&) = delete; \ - ClassName& operator=(const ClassName&) = delete; -#else - #define WTF_MAKE_NONCOPYABLE(ClassName) \ - private: \ - ClassName(const ClassName&); \ - ClassName& operator=(const ClassName&) -#endif +#define WTF_MAKE_NONCOPYABLE(ClassName) \ + private: \ + ClassName(const ClassName&) WTF_DELETED_FUNCTION; \ + ClassName& operator=(const ClassName&) WTF_DELETED_FUNCTION; \ #endif // WTF_Noncopyable_h diff --git a/Source/WTF/wtf/NumberOfCores.cpp b/Source/WTF/wtf/NumberOfCores.cpp index 4bbdb942f..191731acd 100644 --- a/Source/WTF/wtf/NumberOfCores.cpp +++ b/Source/WTF/wtf/NumberOfCores.cpp @@ -34,14 +34,11 @@ #include <sys/sysctl.h> #elif OS(LINUX) || OS(AIX) || OS(SOLARIS) #include <unistd.h> -#elif OS(WINDOWS) || OS(QNX) -#include <wtf/UnusedParam.h> -#if OS(WINDOWS) +#elif OS(WINDOWS) #include <windows.h> #elif OS(QNX) #include <sys/syspage.h> #endif -#endif namespace WTF { diff --git a/Source/WTF/wtf/OSAllocator.h b/Source/WTF/wtf/OSAllocator.h index a12a46749..a57667213 100644 --- a/Source/WTF/wtf/OSAllocator.h +++ b/Source/WTF/wtf/OSAllocator.h @@ -27,7 +27,6 @@ #define OSAllocator_h #include <algorithm> -#include <wtf/UnusedParam.h> #include <wtf/VMTags.h> namespace WTF { @@ -45,14 +44,14 @@ public: // These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state, // releaseDecommitted should be called on a region of VM allocated by a single reservation, // the memory must all currently be in a decommitted state. - static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); + WTF_EXPORT_PRIVATE static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); WTF_EXPORT_PRIVATE static void releaseDecommitted(void*, size_t); // These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should // never be accessed, since the OS may not have attached physical memory for these regions). // Clients should only call commit on uncommitted regions and decommit on committed regions. - static void commit(void*, size_t, bool writable, bool executable); - static void decommit(void*, size_t); + WTF_EXPORT_PRIVATE static void commit(void*, size_t, bool writable, bool executable); + WTF_EXPORT_PRIVATE static void decommit(void*, size_t); // These methods are symmetric; reserveAndCommit allocates VM in an committed state, // decommitAndRelease should be called on a region of VM allocated by a single reservation, @@ -63,7 +62,7 @@ public: // These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than // committing/decommitting the entire region additional parameters allow a subregion to be // specified. - static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false); + WTF_EXPORT_PRIVATE static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false); static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize); // Reallocate an existing, committed allocation. diff --git a/Source/WTF/wtf/OSAllocatorPosix.cpp b/Source/WTF/wtf/OSAllocatorPosix.cpp index a2f6a79bd..a71f39139 100644 --- a/Source/WTF/wtf/OSAllocatorPosix.cpp +++ b/Source/WTF/wtf/OSAllocatorPosix.cpp @@ -26,27 +26,40 @@ #include "config.h" #include "OSAllocator.h" +#if OS(UNIX) + #include "PageAllocation.h" #include <errno.h> #include <sys/mman.h> #include <wtf/Assertions.h> -#include <wtf/UnusedParam.h> namespace WTF { void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages) { #if OS(QNX) + UNUSED_PARAM(usage); + UNUSED_PARAM(writable); + UNUSED_PARAM(executable); + UNUSED_PARAM(includesGuardPages); + // Reserve memory with PROT_NONE and MAP_LAZY so it isn't committed now. void* result = mmap(0, bytes, PROT_NONE, MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0); if (result == MAP_FAILED) CRASH(); -#else // OS(QNX) +#elif OS(LINUX) + UNUSED_PARAM(usage); + UNUSED_PARAM(writable); + UNUSED_PARAM(executable); + UNUSED_PARAM(includesGuardPages); - void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages); -#if OS(LINUX) + void* result = mmap(0, bytes, PROT_NONE, MAP_NORESERVE | MAP_PRIVATE | MAP_ANON, -1, 0); + if (result == MAP_FAILED) + CRASH(); madvise(result, bytes, MADV_DONTNEED); -#elif HAVE(MADV_FREE_REUSE) +#else + void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages); +#if HAVE(MADV_FREE_REUSE) // To support the "reserve then commit" model, we have to initially decommit. while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } #endif @@ -71,18 +84,6 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo flags |= MAP_JIT; #endif -#if (OS(LINUX) && CPU(X86_64)) - // Linux distros usually do not allow overcommit by default, so - // JSC's strategy of mmaping a large amount of memory upfront - // won't work very well on some systems. Fortunately there's a - // flag we can pass to mmap to disable the overcommit check for - // this particular call, so we can get away with it as long as the - // overcommit flag value in /proc/sys/vm/overcommit_memory is 0 - // ('heuristic') and not 2 (always check). 0 is the usual default - // value, so this should work well in general. - flags |= MAP_NORESERVE; -#endif - #if OS(DARWIN) int fd = usage; #else @@ -142,8 +143,13 @@ void OSAllocator::commit(void* address, size_t bytes, bool writable, bool execut if (MAP_FAILED == mmap(address, bytes, protection, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0)) CRASH(); #elif OS(LINUX) - UNUSED_PARAM(writable); - UNUSED_PARAM(executable); + int protection = PROT_READ; + if (writable) + protection |= PROT_WRITE; + if (executable) + protection |= PROT_EXEC; + if (mprotect(address, bytes, protection)) + CRASH(); madvise(address, bytes, MADV_WILLNEED); #elif HAVE(MADV_FREE_REUSE) UNUSED_PARAM(writable); @@ -165,6 +171,8 @@ void OSAllocator::decommit(void* address, size_t bytes) mmap(address, bytes, PROT_NONE, MAP_FIXED | MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0); #elif OS(LINUX) madvise(address, bytes, MADV_DONTNEED); + if (mprotect(address, bytes, PROT_NONE)) + CRASH(); #elif HAVE(MADV_FREE_REUSE) while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } #elif HAVE(MADV_FREE) @@ -185,3 +193,5 @@ void OSAllocator::releaseDecommitted(void* address, size_t bytes) } } // namespace WTF + +#endif // OS(UNIX) diff --git a/Source/WTF/wtf/OSAllocatorWin.cpp b/Source/WTF/wtf/OSAllocatorWin.cpp index 7f5d9b890..78300dc71 100644 --- a/Source/WTF/wtf/OSAllocatorWin.cpp +++ b/Source/WTF/wtf/OSAllocatorWin.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "OSAllocator.h" +#if OS(WINDOWS) + #include "windows.h" #include <wtf/Assertions.h> @@ -78,3 +80,5 @@ void OSAllocator::releaseDecommitted(void* address, size_t bytes) } } // namespace WTF + +#endif // OS(WINDOWS) diff --git a/Source/WTF/wtf/OSRandomSource.cpp b/Source/WTF/wtf/OSRandomSource.cpp index 0c1416a2f..2495abf71 100644 --- a/Source/WTF/wtf/OSRandomSource.cpp +++ b/Source/WTF/wtf/OSRandomSource.cpp @@ -41,7 +41,6 @@ namespace WTF { -#if USE(OS_RANDOMNESS) void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length) { #if OS(UNIX) @@ -66,6 +65,5 @@ void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length) // be of cryptographic quality! #endif } -#endif } diff --git a/Source/WTF/wtf/OSRandomSource.h b/Source/WTF/wtf/OSRandomSource.h index 214a95472..266d44ac2 100644 --- a/Source/WTF/wtf/OSRandomSource.h +++ b/Source/WTF/wtf/OSRandomSource.h @@ -28,14 +28,11 @@ namespace WTF { -#if USE(OS_RANDOMNESS) // This function attempts to fill buffer with randomness from the operating // system. If insufficient randomness is available, the buffer will be // partially filled. Rather than calling this function directly, consider // calling cryptographicallyRandomNumber or cryptographicallyRandomValues. void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length); -#endif - } #endif diff --git a/Source/WTF/wtf/ObjcRuntimeExtras.h b/Source/WTF/wtf/ObjcRuntimeExtras.h index 5420f2757..ec02ed0c0 100644 --- a/Source/WTF/wtf/ObjcRuntimeExtras.h +++ b/Source/WTF/wtf/ObjcRuntimeExtras.h @@ -27,82 +27,16 @@ #include <objc/message.h> -template<typename RetType> -RetType wtfObjcMsgSend(id target, SEL selector) +template<typename RetType, typename... ArgTypes> +RetType wtfObjcMsgSend(id target, SEL selector, ArgTypes... args) { - return reinterpret_cast<RetType (*)(id, SEL)>(objc_msgSend)(target, selector); + return reinterpret_cast<RetType (*)(id, SEL, ArgTypes...)>(objc_msgSend)(target, selector, args...); } -template<typename RetType, typename Arg1Type> -RetType wtfObjcMsgSend(id target, SEL selector, Arg1Type arg1) +template<typename RetType, typename... ArgTypes> +RetType wtfCallIMP(IMP implementation, id target, SEL selector, ArgTypes... args) { - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type)>(objc_msgSend)(target, selector, arg1); + return reinterpret_cast<RetType (*)(id, SEL, ArgTypes...)>(implementation)(target, selector, args...); } -template<typename RetType, typename Arg1Type, typename Arg2Type> -RetType wtfObjcMsgSend(id target, SEL selector, Arg1Type arg1, Arg2Type arg2) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type)>(objc_msgSend)(target, selector, arg1, arg2); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type> -RetType wtfObjcMsgSend(id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type)>(objc_msgSend)(target, selector, arg1, arg2, arg3); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type> -RetType wtfObjcMsgSend(id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type, Arg4Type)>(objc_msgSend)(target, selector, arg1, arg2, arg3, arg4); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type> -RetType wtfObjcMsgSend(id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4, Arg5Type arg5) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type)>(objc_msgSend)(target, selector, arg1, arg2, arg3, arg4, arg5); -} - -template<typename RetType> -RetType wtfCallIMP(IMP implementation, id target, SEL selector) -{ - return reinterpret_cast<RetType (*)(id, SEL)>(implementation)(target, selector); -} - -template<typename RetType, typename Arg1Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type)>(implementation)(target, selector, arg1); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1, Arg2Type arg2) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type)>(implementation)(target, selector, arg1, arg2); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type)>(implementation)(target, selector, arg1, arg2, arg3); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type, Arg4Type)>(implementation)(target, selector, arg1, arg2, arg3, arg4); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4, Arg5Type arg5) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type)>(implementation)(target, selector, arg1, arg2, arg3, arg4, arg5); -} - -template<typename RetType, typename Arg1Type, typename Arg2Type, typename Arg3Type, typename Arg4Type, typename Arg5Type, typename Arg6Type> -RetType wtfCallIMP(IMP implementation, id target, SEL selector, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, Arg4Type arg4, Arg5Type arg5, Arg6Type arg6) -{ - return reinterpret_cast<RetType (*)(id, SEL, Arg1Type, Arg2Type, Arg3Type, Arg4Type, Arg5Type, Arg6Type)>(implementation)(target, selector, arg1, arg2, arg3, arg4, arg5, arg6); -} - -#endif +#endif // WTF_ObjcRuntimeExtras_h diff --git a/Source/WTF/wtf/OwnPtrCommon.h b/Source/WTF/wtf/OwnPtrCommon.h index c56400184..9ac613f3b 100644 --- a/Source/WTF/wtf/OwnPtrCommon.h +++ b/Source/WTF/wtf/OwnPtrCommon.h @@ -42,10 +42,13 @@ typedef struct HRGN__* HRGN; typedef struct _Ecore_Evas Ecore_Evas; typedef struct _Ecore_IMF_Context Ecore_IMF_Context; typedef struct _Ecore_Pipe Ecore_Pipe; -typedef struct _Ecore_Timer Ecore_Timer; typedef struct _Eina_Hash Eina_Hash; typedef struct _Eina_Module Eina_Module; +#if USE(EO) +typedef struct _Eo Evas_Object; +#else typedef struct _Evas_Object Evas_Object; +#endif #if USE(ACCELERATED_COMPOSITING) typedef struct _Evas_GL Evas_GL; #endif @@ -74,7 +77,6 @@ namespace WTF { WTF_EXPORT_PRIVATE void deleteOwnedPtr(Ecore_Evas*); WTF_EXPORT_PRIVATE void deleteOwnedPtr(Ecore_IMF_Context*); WTF_EXPORT_PRIVATE void deleteOwnedPtr(Ecore_Pipe*); - WTF_EXPORT_PRIVATE void deleteOwnedPtr(Ecore_Timer*); WTF_EXPORT_PRIVATE void deleteOwnedPtr(Eina_Hash*); WTF_EXPORT_PRIVATE void deleteOwnedPtr(Eina_Module*); WTF_EXPORT_PRIVATE void deleteOwnedPtr(Evas_Object*); diff --git a/Source/WTF/wtf/PackedIntVector.h b/Source/WTF/wtf/PackedIntVector.h index 9289eb6b3..a245f3a38 100644 --- a/Source/WTF/wtf/PackedIntVector.h +++ b/Source/WTF/wtf/PackedIntVector.h @@ -42,8 +42,8 @@ class PackedIntVector { public: PackedIntVector() { - ASSERT(bitCount); - ASSERT(bitCount < sizeof(void*) * 8); + COMPILE_ASSERT(bitCount, bitCount_shall_not_be_zero); + COMPILE_ASSERT(bitCount < sizeof(void*) * 8, bitCount_shall_not_exceed_address_space_limit); } PackedIntVector(const PackedIntVector& other) diff --git a/Source/WTF/wtf/PageAllocation.h b/Source/WTF/wtf/PageAllocation.h index 18d31880c..95864dc83 100644 --- a/Source/WTF/wtf/PageAllocation.h +++ b/Source/WTF/wtf/PageAllocation.h @@ -29,7 +29,6 @@ #include <wtf/Assertions.h> #include <wtf/OSAllocator.h> #include <wtf/PageBlock.h> -#include <wtf/UnusedParam.h> #include <wtf/VMTags.h> #include <algorithm> diff --git a/Source/WTF/wtf/PageAllocationAligned.cpp b/Source/WTF/wtf/PageAllocationAligned.cpp index 6f54710d0..bdb976b1b 100644 --- a/Source/WTF/wtf/PageAllocationAligned.cpp +++ b/Source/WTF/wtf/PageAllocationAligned.cpp @@ -28,7 +28,7 @@ namespace WTF { -PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignment, OSAllocator::Usage usage, bool writable, bool executable) +PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignment, OSAllocator::Usage usage, bool writable) { ASSERT(isPageAligned(size)); ASSERT(isPageAligned(alignment)); @@ -43,24 +43,22 @@ PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignm int protection = PROT_READ; if (writable) protection |= PROT_WRITE; - if (executable) - protection |= PROT_EXEC; vm_address_t address = 0; - vm_map(current_task(), &address, size, alignmentMask, flags, MEMORY_OBJECT_NULL, 0, FALSE, protection, PROT_READ | PROT_WRITE | PROT_EXEC, VM_INHERIT_DEFAULT); + vm_map(current_task(), &address, size, alignmentMask, flags, MEMORY_OBJECT_NULL, 0, FALSE, protection, PROT_READ | PROT_WRITE, VM_INHERIT_DEFAULT); return PageAllocationAligned(reinterpret_cast<void*>(address), size); #else size_t alignmentDelta = alignment - pageSize(); // Resererve with suffcient additional VM to correctly align. size_t reservationSize = size + alignmentDelta; - void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable, executable); + void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable, false); // Select an aligned region within the reservation and commit. void* alignedBase = reinterpret_cast<uintptr_t>(reservationBase) & alignmentMask ? reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(reservationBase) & ~alignmentMask) + alignment) : reservationBase; - OSAllocator::commit(alignedBase, size, writable, executable); + OSAllocator::commit(alignedBase, size, writable, false); return PageAllocationAligned(alignedBase, size, reservationBase, reservationSize); #endif diff --git a/Source/WTF/wtf/PageAllocationAligned.h b/Source/WTF/wtf/PageAllocationAligned.h index c018dabd8..5513d135d 100644 --- a/Source/WTF/wtf/PageAllocationAligned.h +++ b/Source/WTF/wtf/PageAllocationAligned.h @@ -41,9 +41,9 @@ public: using PageBlock::size; using PageBlock::base; - static PageAllocationAligned allocate(size_t size, size_t alignment, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false); + WTF_EXPORT_PRIVATE static PageAllocationAligned allocate(size_t size, size_t alignment, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true); - void deallocate(); + WTF_EXPORT_PRIVATE void deallocate(); private: #if OS(DARWIN) diff --git a/Source/WTF/wtf/PassOwnPtr.h b/Source/WTF/wtf/PassOwnPtr.h index 5ebf83d65..cb8753905 100644 --- a/Source/WTF/wtf/PassOwnPtr.h +++ b/Source/WTF/wtf/PassOwnPtr.h @@ -39,6 +39,9 @@ namespace WTF { template<typename T> class PassOwnPtr; template<typename T> PassOwnPtr<T> adoptPtr(T*); + class RefCountedBase; + class ThreadSafeRefCountedBase; + template<typename T> class PassOwnPtr { public: typedef typename RemovePointer<T>::Type ValueType; @@ -144,6 +147,9 @@ namespace WTF { template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr) { + COMPILE_ASSERT(!(IsSubclass<T, RefCountedBase>::value), DoNotUseAdoptPtrWithRefCounted); + COMPILE_ASSERT(!(IsSubclass<T, ThreadSafeRefCountedBase>::value), DoNotUseAdoptPtrWithThreadSafeRefCounted); + return PassOwnPtr<T>(ptr); } diff --git a/Source/WTF/wtf/PassRefPtr.h b/Source/WTF/wtf/PassRefPtr.h index 5f5067113..1e1c777ad 100644 --- a/Source/WTF/wtf/PassRefPtr.h +++ b/Source/WTF/wtf/PassRefPtr.h @@ -21,7 +21,6 @@ #ifndef WTF_PassRefPtr_h #define WTF_PassRefPtr_h -#include <wtf/AlwaysInline.h> #include <wtf/Assertions.h> #include <wtf/NullPtr.h> diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h index 35fa7e3da..37dd12f97 100644 --- a/Source/WTF/wtf/Platform.h +++ b/Source/WTF/wtf/Platform.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved. * @@ -65,6 +65,11 @@ #define WTF_CPU_ALPHA 1 #endif +/* CPU(HPPA) - HP PA-RISC */ +#if defined(__hppa__) || defined(__hppa64__) +#define WTF_CPU_HPPA 1 +#endif + /* CPU(IA64) - Itanium / IA-64 */ #if defined(__ia64__) #define WTF_CPU_IA64 1 @@ -163,6 +168,8 @@ #endif /* CPU(ARM) - ARM, any version*/ +#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) + #if defined(arm) \ || defined(__arm__) \ || defined(ARM) \ @@ -179,19 +186,15 @@ #elif !defined(__ARM_EABI__) \ && !defined(__EABI__) \ && !defined(__VFP_FP__) \ - && !defined(_WIN32_WCE) \ - && !defined(ANDROID) + && !defined(_WIN32_WCE) #define WTF_CPU_MIDDLE_ENDIAN 1 #endif -#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) - /* Set WTF_ARM_ARCH_VERSION */ #if defined(__ARM_ARCH_4__) \ || defined(__ARM_ARCH_4T__) \ - || defined(__MARM_ARMV4__) \ - || defined(_ARMV4I_) + || defined(__MARM_ARMV4__) #define WTF_ARM_ARCH_VERSION 4 #elif defined(__ARM_ARCH_5__) \ @@ -216,9 +219,14 @@ #define WTF_ARM_ARCH_VERSION 6 #elif defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7S__) #define WTF_ARM_ARCH_VERSION 7 +/* MSVC sets _M_ARM */ +#elif defined(_M_ARM) +#define WTF_ARM_ARCH_VERSION _M_ARM + /* RVCT sets _TARGET_ARCH_ARM */ #elif defined(__TARGET_ARCH_ARM) #define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM @@ -254,8 +262,9 @@ #elif defined(__ARM_ARCH_6T2__) \ || defined(__ARM_ARCH_7__) \ || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7M__) \ || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7M__) + || defined(__ARM_ARCH_7S__) #define WTF_THUMB_ARCH_VERSION 4 /* RVCT sets __TARGET_ARCH_THUMB */ @@ -319,11 +328,6 @@ /* ==== OS() - underlying operating system; only to be used for mandated low-level services like virtual memory, not to choose a GUI toolkit ==== */ -/* OS(ANDROID) - Android */ -#ifdef ANDROID -#define WTF_OS_ANDROID 1 -#endif - /* OS(AIX) - AIX */ #ifdef _AIX #define WTF_OS_AIX 1 @@ -410,8 +414,7 @@ #define WTF_OS_MAC ERROR "USE MAC_OS_X WITH OS NOT MAC" /* OS(UNIX) - Any Unix-like system */ -#if OS(AIX) \ - || OS(ANDROID) \ +#if OS(AIX) \ || OS(DARWIN) \ || OS(FREEBSD) \ || OS(HURD) \ @@ -429,20 +432,14 @@ /* Operating environments */ /* FIXME: these are all mixes of OS, operating environment and policy choices. */ -/* PLATFORM(CHROMIUM) */ /* PLATFORM(QT) */ -/* PLATFORM(WX) */ /* PLATFORM(EFL) */ /* PLATFORM(GTK) */ /* PLATFORM(BLACKBERRY) */ /* PLATFORM(MAC) */ /* PLATFORM(WIN) */ -#if defined(BUILDING_CHROMIUM__) -#define WTF_PLATFORM_CHROMIUM 1 -#elif defined(BUILDING_QT__) +#if defined(BUILDING_QT__) #define WTF_PLATFORM_QT 1 -#elif defined(BUILDING_WX__) -#define WTF_PLATFORM_WX 1 #elif defined(BUILDING_EFL__) #define WTF_PLATFORM_EFL 1 #elif defined(BUILDING_GTK__) @@ -470,38 +467,14 @@ /* Graphics engines */ /* USE(CG) and PLATFORM(CI) */ -#if PLATFORM(MAC) || PLATFORM(IOS) +#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && !USE(WINGDI) && !PLATFORM(WIN_CAIRO)) #define WTF_USE_CG 1 #endif #if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && USE(CG)) #define WTF_USE_CA 1 #endif -/* USE(SKIA) for Win/Linux/Mac/Android */ -#if PLATFORM(CHROMIUM) -#if OS(DARWIN) -#define WTF_USE_SKIA 1 -#define WTF_USE_ICCJPEG 1 -#define WTF_USE_QCMSLIB 1 -#elif OS(ANDROID) -#define WTF_USE_SKIA 1 -#define WTF_USE_LOW_QUALITY_IMAGE_INTERPOLATION 1 -#define WTF_USE_LOW_QUALITY_IMAGE_NO_JPEG_DITHERING 1 -#define WTF_USE_LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING 1 -#else -#define WTF_USE_SKIA 1 -#define WTF_USE_ICCJPEG 1 -#define WTF_USE_QCMSLIB 1 -#endif -#endif - -#if OS(QNX) -#define USE_SYSTEM_MALLOC 1 -#endif - #if PLATFORM(BLACKBERRY) -#define WTF_USE_MERSENNE_TWISTER_19937 1 -#define WTF_USE_SKIA 1 #define WTF_USE_LOW_QUALITY_IMAGE_INTERPOLATION 1 #define WTF_USE_LOW_QUALITY_IMAGE_NO_JPEG_DITHERING 1 #define WTF_USE_LOW_QUALITY_IMAGE_NO_JPEG_FANCY_UPSAMPLING 1 @@ -509,12 +482,13 @@ #if PLATFORM(GTK) #define WTF_USE_CAIRO 1 +#define WTF_USE_GLIB 1 +#define WTF_USE_FREETYPE 1 +#define WTF_USE_HARFBUZZ 1 +#define WTF_USE_SOUP 1 +#define WTF_USE_WEBP 1 #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 -#endif - - -#if OS(WINCE) -#define WTF_USE_MERSENNE_TWISTER_19937 1 +#define GST_API_VERSION_1 1 #endif /* On Windows, use QueryPerformanceCounter by default */ @@ -533,11 +507,7 @@ #endif /* OS(WINCE) && !PLATFORM(QT) */ -#if OS(WINCE) && !PLATFORM(QT) -#define WTF_USE_WCHAR_UNICODE 1 -#elif PLATFORM(GTK) -/* The GTK+ Unicode backend is configurable */ -#else +#if !USE(WCHAR_UNICODE) #define WTF_USE_ICU_UNICODE 1 #endif @@ -546,25 +516,12 @@ #define WTF_USE_PLUGIN_HOST_PROCESS 1 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 -#define ENABLE_GESTURE_EVENTS 1 -#define ENABLE_RUBBER_BANDING 1 #define WTF_USE_SCROLLBAR_PAINTER 1 #define HAVE_XPC 1 #endif -#if !defined(ENABLE_DASHBOARD_SUPPORT) -#define ENABLE_DASHBOARD_SUPPORT 1 -#endif #define WTF_USE_CF 1 -#define WTF_USE_PTHREADS 1 #define HAVE_READLINE 1 #define HAVE_RUNLOOP_TIMER 1 -#define ENABLE_FULLSCREEN_API 1 -#define ENABLE_SMOOTH_SCROLLING 1 -#define ENABLE_WEB_ARCHIVE 1 -#define ENABLE_WEB_AUDIO 1 -#if defined(ENABLE_VIDEO) -#define ENABLE_VIDEO_TRACK 1 -#endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 #define HAVE_LAYER_HOSTING_IN_WINDOW_SERVER 1 #endif @@ -572,24 +529,6 @@ #define WTF_USE_SECURITY_FRAMEWORK 1 #endif /* PLATFORM(MAC) && !PLATFORM(IOS) */ -#if PLATFORM(CHROMIUM) && OS(DARWIN) -#define WTF_USE_CF 1 -#define WTF_USE_PTHREADS 1 -#define WTF_USE_WK_SCROLLBAR_PAINTER 1 -#endif - -#if PLATFORM(CHROMIUM) -#if OS(DARWIN) -/* We can't override the global operator new and delete on OS(DARWIN) because - * some object are allocated by WebKit and deallocated by the embedder. */ -#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 -#else /* !OS(DARWIN) */ -/* On non-OS(DARWIN), the "system malloc" is actually TCMalloc anyway, so there's - * no need to use WebKit's copy of TCMalloc. */ -#define USE_SYSTEM_MALLOC 1 -#endif /* OS(DARWIN) */ -#endif /* PLATFORM(CHROMIUM) */ - #if PLATFORM(IOS) #define DONT_FINALIZE_ON_MAIN_THREAD 1 #endif @@ -603,39 +542,20 @@ #endif #if PLATFORM(IOS) -#define ENABLE_CONTEXT_MENUS 0 -#define ENABLE_DRAG_SUPPORT 0 -#define ENABLE_GEOLOCATION 1 -#define ENABLE_ICONDATABASE 0 -#define ENABLE_INSPECTOR 1 -#define ENABLE_NETSCAPE_PLUGIN_API 0 -#define ENABLE_ORIENTATION_EVENTS 1 -#define ENABLE_REPAINT_THROTTLING 1 -#define ENABLE_WEB_ARCHIVE 1 #define HAVE_READLINE 1 +#define WTF_USE_APPKIT 0 #define WTF_USE_CF 1 #define WTF_USE_CFNETWORK 1 #define WTF_USE_NETWORK_CFDATA_ARRAY_CALLBACK 1 -#define WTF_USE_PTHREADS 1 - -#if PLATFORM(IOS_SIMULATOR) - #define ENABLE_JIT 0 - #define ENABLE_YARR_JIT 0 -#else - #define ENABLE_JIT 1 - #define ENABLE_LLINT 1 - #define ENABLE_YARR_JIT 1 -#endif - -#define WTF_USE_APPKIT 0 #define WTF_USE_SECURITY_FRAMEWORK 0 -#endif +#define WTF_USE_WEB_THREAD 1 +#endif /* PLATFORM(IOS) */ -#if PLATFORM(WIN) && !OS(WINCE) +#if PLATFORM(WIN) && !USE(WINGDI) #define WTF_USE_CF 1 #endif -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) +#if PLATFORM(WIN) && !USE(WINGDI) && !PLATFORM(WIN_CAIRO) #define WTF_USE_CFNETWORK 1 #endif @@ -643,42 +563,24 @@ #define WTF_USE_CFURLCACHE 1 #endif -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT) -#define ENABLE_WEB_ARCHIVE 1 -#endif - -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) && !PLATFORM(QT) -#define ENABLE_FULLSCREEN_API 1 -#endif - -#if PLATFORM(WX) -#if !CPU(PPC) -#if !defined(ENABLE_ASSEMBLER) -#define ENABLE_ASSEMBLER 1 -#endif -#define ENABLE_JIT 1 -#endif -#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 -#define ENABLE_LLINT 0 -#if OS(DARWIN) -#define WTF_USE_CF 1 -#define ENABLE_WEB_ARCHIVE 1 -#endif -#endif - -#if OS(UNIX) && (PLATFORM(GTK) || PLATFORM(QT)) -#define WTF_USE_PTHREADS 1 -#endif - #if !defined(HAVE_ACCESSIBILITY) -#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && !OS(ANDROID)) || PLATFORM(EFL) +#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(EFL) #define HAVE_ACCESSIBILITY 1 #endif #endif /* !defined(HAVE_ACCESSIBILITY) */ #if OS(UNIX) +#define HAVE_ERRNO_H 1 +#define HAVE_MMAP 1 #define HAVE_SIGNAL_H 1 -#define WTF_USE_OS_RANDOMNESS 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 +#define WTF_USE_PTHREADS 1 +#endif /* OS(UNIX) */ + +#if OS(UNIX) && !OS(QNX) +#define HAVE_LANGINFO_H 1 #endif #if (OS(FREEBSD) || OS(OPENBSD)) && !defined(__GLIBC__) @@ -697,9 +599,7 @@ #endif #endif -#if !OS(WINDOWS) && !OS(SOLARIS) \ - && !OS(RVCT) \ - && !OS(ANDROID) +#if !OS(WINDOWS) && !OS(SOLARIS) #define HAVE_TM_GMTOFF 1 #define HAVE_TM_ZONE 1 #define HAVE_TIMEGM 1 @@ -707,78 +607,47 @@ #if OS(DARWIN) -#define HAVE_ERRNO_H 1 -#define HAVE_LANGINFO_H 1 -#define HAVE_MMAP 1 +#define HAVE_DISPATCH_H 1 +#define HAVE_MADV_FREE 1 +#define HAVE_MADV_FREE_REUSE 1 #define HAVE_MERGESORT 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 +#define HAVE_PTHREAD_SETNAME_NP 1 #define HAVE_SYS_TIMEB_H 1 #define WTF_USE_ACCELERATE 1 -#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - -#define HAVE_DISPATCH_H 1 -#define HAVE_HOSTED_CORE_ANIMATION 1 - #if !PLATFORM(IOS) -#define HAVE_MADV_FREE_REUSE 1 -#define HAVE_MADV_FREE 1 -#define HAVE_PTHREAD_SETNAME_NP 1 -#endif - -#endif - -#if PLATFORM(IOS) -#define HAVE_MADV_FREE 1 -#define HAVE_PTHREAD_SETNAME_NP 1 -#endif +#define HAVE_HOSTED_CORE_ANIMATION 1 +#endif /* !PLATFORM(IOS) */ -#elif OS(WINDOWS) +#endif /* OS(DARWIN) */ -#if !OS(WINCE) +#if OS(WINDOWS) && !OS(WINCE) #define HAVE_SYS_TIMEB_H 1 #define HAVE_ALIGNED_MALLOC 1 #define HAVE_ISDEBUGGERPRESENT 1 + +#if !PLATFORM(QT) +#include <WTF/WTFHeaderDetection.h> #endif -#define HAVE_VIRTUALALLOC 1 -#define WTF_USE_OS_RANDOMNESS 1 -#elif OS(QNX) +#endif -#define HAVE_ERRNO_H 1 -#define HAVE_MMAP 1 +#if OS(WINDOWS) +#define HAVE_VIRTUALALLOC 1 +#endif + +#if OS(QNX) #define HAVE_MADV_FREE_REUSE 1 #define HAVE_MADV_FREE 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 -#define WTF_USE_PTHREADS 1 - -#elif OS(ANDROID) - -#define HAVE_ERRNO_H 1 -#define HAVE_NMAP 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 - -#else - -/* FIXME: is this actually used or do other platforms generate their own config.h? */ - -#define HAVE_ERRNO_H 1 -#define HAVE_LANGINFO_H 1 -#define HAVE_MMAP 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 - #endif /* ENABLE macro defaults */ +/* FIXME: move out all ENABLE() defines from here to FeatureDefines.h */ + +/* Include feature macros */ +#include <wtf/FeatureDefines.h> + #if PLATFORM(QT) /* We must not customize the global operator new and delete for the Qt port. */ #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 @@ -787,66 +656,18 @@ #endif #endif -#if !defined(ENABLE_ICONDATABASE) -#define ENABLE_ICONDATABASE 1 -#endif - -#if !defined(ENABLE_SQL_DATABASE) -#define ENABLE_SQL_DATABASE 1 -#endif - -#if !defined(ENABLE_JAVASCRIPT_DEBUGGER) -#define ENABLE_JAVASCRIPT_DEBUGGER 1 -#endif - -#if !defined(ENABLE_FTPDIR) -#define ENABLE_FTPDIR 1 -#endif - -#if !defined(ENABLE_CONTEXT_MENUS) -#define ENABLE_CONTEXT_MENUS 1 -#endif - -#if !defined(ENABLE_DRAG_SUPPORT) -#define ENABLE_DRAG_SUPPORT 1 -#endif - -#if !defined(ENABLE_INSPECTOR) -#define ENABLE_INSPECTOR 1 +#if PLATFORM(EFL) +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 #endif -#if !defined(ENABLE_NETSCAPE_PLUGIN_API) -#define ENABLE_NETSCAPE_PLUGIN_API 1 +#if OS(WINDOWS) +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 #endif #if !defined(ENABLE_GLOBAL_FASTMALLOC_NEW) #define ENABLE_GLOBAL_FASTMALLOC_NEW 1 #endif -#if !defined(ENABLE_PARSED_STYLE_SHEET_CACHING) -#define ENABLE_PARSED_STYLE_SHEET_CACHING 1 -#endif - -#if !defined(ENABLE_SUBPIXEL_LAYOUT) -#if PLATFORM(CHROMIUM) -#define ENABLE_SUBPIXEL_LAYOUT 1 -#else -#define ENABLE_SUBPIXEL_LAYOUT 0 -#endif -#endif - -#if !defined(ENABLE_SATURATED_LAYOUT_ARITHMETIC) -#define ENABLE_SATURATED_LAYOUT_ARITHMETIC 0 -#endif - -#if ENABLE(ENABLE_SATURATED_LAYOUT_ARITHMETIC) && !ENABLE(ENABLE_SUBPIXEL_LAYOUT) -#error "ENABLE_SATURATED_LAYOUT_ARITHMETIC requires ENABLE_SUBPIXEL_LAYOUT" -#endif - -#if ENABLE(INPUT_TYPE_DATE) || ENABLE(INPUT_TYPE_DATETIME) || ENABLE(INPUT_TYPE_DATETIMELOCAL) || ENABLE(INPUT_TYPE_MONTH) || ENABLE(INPUT_TYPE_TIME) || ENABLE(INPUT_TYPE_WEEK) -#define ENABLE_DATE_AND_TIME_INPUT_TYPES 1 -#endif - #define ENABLE_DEBUG_WITH_BREAKPOINT 0 #define ENABLE_SAMPLING_COUNTERS 0 #define ENABLE_SAMPLING_FLAGS 0 @@ -860,10 +681,6 @@ #define ENABLE_SAMPLING_THREAD 1 #endif -#if !defined(ENABLE_TEXT_CARET) && !PLATFORM(IOS) -#define ENABLE_TEXT_CARET 1 -#endif - #if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) #if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \ || (CPU(IA64) && !CPU(IA64_32)) \ @@ -891,7 +708,7 @@ && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \ && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \ && !OS(WINCE) \ - && !OS(QNX) + && !(OS(QNX) && !PLATFORM(QT)) /* We use JIT in QNX Qt */ #define ENABLE_JIT 1 #endif @@ -903,16 +720,12 @@ #define WTF_USE_UDIS86 1 #endif -#if !defined(ENABLE_DISASSEMBLER) && USE(UDIS86) -#define ENABLE_DISASSEMBLER 1 +#if !defined(WTF_USE_ARMV7_DISASSEMBLER) && ENABLE(JIT) && PLATFORM(IOS) && CPU(ARM_THUMB2) +#define WTF_USE_ARMV7_DISASSEMBLER 1 #endif -/* On the GTK+ port we take an extra precaution for LLINT support: - * We disable it on x86 builds if the build target doesn't support SSE2 - * instructions (LLINT requires SSE2 on this platform). */ -#if !defined(ENABLE_LLINT) && PLATFORM(GTK) && CPU(X86) && COMPILER(GCC) \ - && !defined(__SSE2__) -#define ENABLE_LLINT 0 +#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER)) +#define ENABLE_DISASSEMBLER 1 #endif /* On some of the platforms where we have a JIT, we want to also have the @@ -921,25 +734,21 @@ && ENABLE(JIT) \ && (OS(DARWIN) || OS(LINUX)) \ && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(QT)) \ - && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2) || CPU(MIPS)) + && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL) || CPU(MIPS) || CPU(SH4)) #define ENABLE_LLINT 1 #endif #if !defined(ENABLE_DFG_JIT) && ENABLE(JIT) && !COMPILER(MSVC) /* 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)) +#if (CPU(X86) || CPU(X86_64)) && (OS(DARWIN) || OS(LINUX)) #define ENABLE_DFG_JIT 1 #endif /* Enable the DFG JIT on ARMv7. Only tested on iOS and Qt Linux. */ #if CPU(ARM_THUMB2) && (PLATFORM(IOS) || PLATFORM(BLACKBERRY) || PLATFORM(QT)) #define ENABLE_DFG_JIT 1 #endif -/* Enable the DFG JIT on ARM. */ -#if CPU(ARM_TRADITIONAL) -#define ENABLE_DFG_JIT 1 -#endif -/* Enable the DFG JIT on MIPS. */ -#if CPU(MIPS) +/* Enable the DFG JIT on ARM, MIPS and SH4. */ +#if CPU(ARM_TRADITIONAL) || CPU(MIPS) || CPU(SH4) #define ENABLE_DFG_JIT 1 #endif #endif @@ -982,6 +791,16 @@ #define ENABLE_WRITE_BARRIER_PROFILING 0 #endif +/* Enable verification that that register allocations are not made within generated control flow. + Turned on for debug builds. */ +#if !defined(ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION) && ENABLE(DFG_JIT) +#if !defined(NDEBUG) +#define ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION 1 +#else +#define ENABLE_DFG_REGISTER_ALLOCATION_VALIDATION 0 +#endif +#endif + /* Configure the JIT */ #if CPU(X86) && COMPILER(MSVC) #define JSC_HOST_CALL __fastcall @@ -992,7 +811,7 @@ #endif /* Configure the interpreter */ -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) +#if COMPILER(GCC) || (COMPILER(RVCT) && defined(__GNUC__)) #define HAVE_COMPUTED_GOTO 1 #endif @@ -1005,7 +824,7 @@ #define ENABLE_REGEXP_TRACING 0 /* Yet Another Regex Runtime - turned on by default for JIT enabled ports. */ -#if !defined(ENABLE_YARR_JIT) && (ENABLE(JIT) || ENABLE(LLINT_C_LOOP)) && !PLATFORM(CHROMIUM) +#if !defined(ENABLE_YARR_JIT) && (ENABLE(JIT) || ENABLE(LLINT_C_LOOP)) && !(OS(QNX) && PLATFORM(QT)) #define ENABLE_YARR_JIT 1 /* Setting this flag compares JIT results with interpreter results. */ @@ -1033,15 +852,6 @@ #endif #endif -#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS) -#define ENABLE_PAN_SCROLLING 1 -#endif - -/*Add other platforms as they update their platfrom specific code to handle TextRun's with 8 bit data. */ -#if PLATFORM(MAC) -#define ENABLE_8BIT_TEXTRUN 1 -#endif - /* Use the QXmlStreamReader implementation for XMLDocumentParser */ /* Use the QXmlQuery implementation for XSLTProcessor */ #if PLATFORM(QT) @@ -1052,14 +862,10 @@ #endif /* Accelerated compositing */ -#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) +#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !USE(WINGDI) && !PLATFORM(WIN_CAIRO)) #define WTF_USE_ACCELERATED_COMPOSITING 1 #endif -#if PLATFORM(MAC) || PLATFORM(IOS) -#define ENABLE_CSS_IMAGE_SET 1 -#endif - #if ENABLE(WEBGL) && !defined(WTF_USE_3D_GRAPHICS) #define WTF_USE_3D_GRAPHICS 1 #endif @@ -1074,7 +880,7 @@ #endif /* Compositing on the UI-process in WebKit2 */ -#if PLATFORM(QT) +#if USE(3D_GRAPHICS) && PLATFORM(QT) #define WTF_USE_COORDINATED_GRAPHICS 1 #endif @@ -1082,22 +888,9 @@ #define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 #endif -#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(EFL))) -#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 -#endif - -#if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 -#define ENABLE_THREADED_SCROLLING 1 -#endif - /* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */ #define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK -/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */ -#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) -#define WTF_USE_PLATFORM_STRATEGIES 1 -#endif - #if PLATFORM(WIN) #define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1 #endif @@ -1118,7 +911,7 @@ #define ENABLE_THREADING_GENERIC 1 #endif -#if ENABLE(GLIB_SUPPORT) +#if USE(GLIB) #include <wtf/gobject/GTypedefs.h> #endif @@ -1126,7 +919,7 @@ since most ports try to support sub-project independence, adding new headers to WTF causes many ports to break, and so this way we can address the build breakages one port at a time. */ -#if !defined(WTF_USE_EXPORT_MACROS) && (PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(WX)) +#if !defined(WTF_USE_EXPORT_MACROS) && (PLATFORM(MAC) || PLATFORM(QT) || (PLATFORM(WIN) && (defined(_MSC_VER) && _MSC_VER >= 1600))) #define WTF_USE_EXPORT_MACROS 1 #endif @@ -1138,58 +931,62 @@ #define WTF_USE_UNIX_DOMAIN_SOCKETS 1 #endif +#if !defined(WTF_USE_IMLANG_FONT_LINK2) && !OS(WINCE) +#define WTF_USE_IMLANG_FONT_LINK2 1 +#endif + #if !defined(ENABLE_COMPARE_AND_SWAP) && (OS(WINDOWS) || (COMPILER(GCC) && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2)))) #define ENABLE_COMPARE_AND_SWAP 1 #endif #define ENABLE_OBJECT_MARK_LOGGING 0 -#if !defined(ENABLE_PARALLEL_GC) && !ENABLE(OBJECT_MARK_LOGGING) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(BLACKBERRY) || PLATFORM(GTK)) && ENABLE(COMPARE_AND_SWAP) +#if !defined(ENABLE_PARALLEL_GC) && !ENABLE(OBJECT_MARK_LOGGING) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || PLATFORM(BLACKBERRY) || PLATFORM(GTK)) && ENABLE(COMPARE_AND_SWAP) #define ENABLE_PARALLEL_GC 1 -#elif PLATFORM(QT) -// Parallel GC is temporarily disabled on Qt because of regular crashes, see https://bugs.webkit.org/show_bug.cgi?id=90957 for details -#define ENABLE_PARALLEL_GC 0 #endif #if !defined(ENABLE_GC_VALIDATION) && !defined(NDEBUG) #define ENABLE_GC_VALIDATION 1 #endif +#if !defined(ENABLE_BINDING_INTEGRITY) && !OS(WINDOWS) +#define ENABLE_BINDING_INTEGRITY 1 +#endif + #if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 #define WTF_USE_AVFOUNDATION 1 #endif -#if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) #define WTF_USE_COREMEDIA 1 #endif -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(BLACKBERRY) -#define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1 +#if (PLATFORM(MAC) || (OS(WINDOWS) && USE(CG))) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#define HAVE_AVFOUNDATION_MEDIA_SELECTION_GROUP 1 #endif -#if PLATFORM(MAC) || PLATFORM(BLACKBERRY) -#define WTF_USE_REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR 1 +#if (PLATFORM(MAC) || (OS(WINDOWS) && USE(CG))) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#define HAVE_AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT 1 #endif -#if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) -#define HAVE_INVERTED_WHEEL_EVENTS 1 +#if (PLATFORM(MAC) || (OS(WINDOWS) && USE(CG))) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#define HAVE_MEDIA_ACCESSIBILITY_FRAMEWORK 1 #endif -#if PLATFORM(MAC) -#define WTF_USE_COREAUDIO 1 +#if PLATFORM(MAC) || PLATFORM(GTK) || (PLATFORM(WIN) && !USE(WINGDI) && !PLATFORM(WIN_CAIRO)) +#define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1 #endif -#if !defined(WTF_USE_V8) && PLATFORM(CHROMIUM) -#define WTF_USE_V8 1 +#if PLATFORM(MAC) +#define WTF_USE_REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR 1 #endif -/* Not using V8 implies using JSC and vice versa */ -#if !USE(V8) -#define WTF_USE_JSC 1 +#if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +#define HAVE_INVERTED_WHEEL_EVENTS 1 #endif -#if ENABLE(NOTIFICATIONS) && PLATFORM(MAC) -#define ENABLE_TEXT_NOTIFICATIONS_ONLY 1 +#if PLATFORM(MAC) +#define WTF_USE_COREAUDIO 1 #endif #if !defined(WTF_USE_ZLIB) && !PLATFORM(QT) @@ -1203,4 +1000,29 @@ #endif #endif +#if !PLATFORM(IOS) && PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +#define WTF_USE_CONTENT_FILTERING 1 +#endif + + +#define WTF_USE_GRAMMAR_CHECKING 1 + +#if PLATFORM(MAC) || PLATFORM(BLACKBERRY) || PLATFORM(EFL) +#define WTF_USE_UNIFIED_TEXT_CHECKING 1 +#endif +#if PLATFORM(MAC) +#define WTF_USE_AUTOMATIC_TEXT_REPLACEMENT 1 +#endif + +#if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) +/* Some platforms provide UI for suggesting autocorrection. */ +#define WTF_USE_AUTOCORRECTION_PANEL 1 +/* Some platforms use spelling and autocorrection markers to provide visual cue. On such platform, if word with marker is edited, we need to remove the marker. */ +#define WTF_USE_MARKER_REMOVAL_UPON_EDITING 1 +#endif /* #if PLATFORM(MAC) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) */ + +#if PLATFORM(MAC) || PLATFORM(IOS) +#define WTF_USE_AUDIO_SESSION 1 +#endif + #endif /* WTF_Platform_h */ diff --git a/Source/WTF/wtf/PlatformBlackBerry.cmake b/Source/WTF/wtf/PlatformBlackBerry.cmake index 5f30d0889..b5de30523 100644 --- a/Source/WTF/wtf/PlatformBlackBerry.cmake +++ b/Source/WTF/wtf/PlatformBlackBerry.cmake @@ -1,12 +1,3 @@ -LIST(APPEND WTF_SOURCES - OSAllocatorPosix.cpp - TCSystemAlloc.cpp - ThreadIdentifierDataPthreads.cpp - ThreadingPthreads.cpp +list(APPEND WTF_SOURCES blackberry/MainThreadBlackBerry.cpp - unicode/icu/CollatorICU.cpp -) - -LIST(INSERT WTF_INCLUDE_DIRECTORIES 0 - "${BLACKBERRY_THIRD_PARTY_DIR}/icu" ) diff --git a/Source/WTF/wtf/PlatformEfl.cmake b/Source/WTF/wtf/PlatformEfl.cmake index 73d57e5cf..c59f4972f 100644 --- a/Source/WTF/wtf/PlatformEfl.cmake +++ b/Source/WTF/wtf/PlatformEfl.cmake @@ -1,40 +1,31 @@ -LIST(APPEND WTF_SOURCES +list(APPEND WTF_SOURCES efl/MainThreadEfl.cpp efl/OwnPtrEfl.cpp efl/RefPtrEfl.cpp + gobject/GOwnPtr.cpp gobject/GRefPtr.cpp - - OSAllocatorPosix.cpp - ThreadIdentifierDataPthreads.cpp - ThreadingPthreads.cpp - - unicode/icu/CollatorICU.cpp ) -LIST(APPEND WTF_LIBRARIES +list(APPEND WTF_LIBRARIES pthread ${GLIB_LIBRARIES} ${GLIB_GIO_LIBRARIES} ${GLIB_GOBJECT_LIBRARIES} - ${ICU_LIBRARIES} - ${ICU_I18N_LIBRARIES} ${ECORE_LIBRARIES} ${ECORE_EVAS_LIBRARIES} ${ECORE_IMF_LIBRARIES} ${EINA_LIBRARIES} + ${EO_LIBRARIES} ${EVAS_LIBRARIES} - ${CMAKE_DL_LIBS} ) -LIST(APPEND WTF_INCLUDE_DIRECTORIES - ${ECORE_INCLUDE_DIRS} +list(APPEND WTF_INCLUDE_DIRECTORIES ${ECORE_EVAS_INCLUDE_DIRS} + ${ECORE_INCLUDE_DIRS} + ${ECORE_IMF_INCLUDE_DIRS} ${EINA_INCLUDE_DIRS} + ${EO_INCLUDE_DIRS} ${EVAS_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} - ${ICU_INCLUDE_DIRS} - ${JAVASCRIPTCORE_DIR}/wtf/gobject - ${JAVASCRIPTCORE_DIR}/wtf/unicode - ${JAVASCRIPTCORE_DIR}/wtf/efl ) diff --git a/Source/WTF/wtf/PlatformGTK.cmake b/Source/WTF/wtf/PlatformGTK.cmake new file mode 100644 index 000000000..500216e75 --- /dev/null +++ b/Source/WTF/wtf/PlatformGTK.cmake @@ -0,0 +1,18 @@ +list(APPEND WTF_SOURCES + gobject/GlibUtilities.cpp + gobject/GOwnPtr.cpp + gobject/GRefPtr.cpp + + gtk/MainThreadGtk.cpp +) + +list(APPEND WTF_LIBRARIES + pthread + ${GLIB_LIBRARIES} + ${GLIB_GIO_LIBRARIES} + ${GLIB_GOBJECT_LIBRARIES} +) + +list(APPEND WTF_INCLUDE_DIRECTORIES + ${GLIB_INCLUDE_DIRS} +) diff --git a/Source/WTF/wtf/PlatformWinCE.cmake b/Source/WTF/wtf/PlatformWinCE.cmake index d558ee579..6a91c50c1 100644 --- a/Source/WTF/wtf/PlatformWinCE.cmake +++ b/Source/WTF/wtf/PlatformWinCE.cmake @@ -1,22 +1,9 @@ -LIST(APPEND WTF_HEADERS - unicode/wchar/UnicodeWchar.h -) - -LIST(APPEND WTF_SOURCES - NullPtr.cpp - OSAllocatorWin.cpp - ThreadingWin.cpp - ThreadSpecificWin.cpp - +list(APPEND WTF_SOURCES threads/win/BinarySemaphoreWin.cpp - unicode/CollatorDefault.cpp - unicode/wchar/UnicodeWchar.cpp - win/MainThreadWin.cpp - win/OwnPtrWin.cpp ) -LIST(APPEND WTF_LIBRARIES +list(APPEND WTF_LIBRARIES mmtimer ) diff --git a/Source/WTF/wtf/PrintStream.h b/Source/WTF/wtf/PrintStream.h index 88329fd97..2ae27e75b 100644 --- a/Source/WTF/wtf/PrintStream.h +++ b/Source/WTF/wtf/PrintStream.h @@ -44,7 +44,7 @@ public: PrintStream(); virtual ~PrintStream(); - void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); + WTF_EXPORT_PRIVATE void printf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0) = 0; // Typically a no-op for many subclasses of PrintStream, this is a hint that @@ -155,24 +155,75 @@ public: print(value9); print(value10); } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11> + void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11) + { + print(value1); + print(value2); + print(value3); + print(value4); + print(value5); + print(value6); + print(value7); + print(value8); + print(value9); + print(value10); + print(value11); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12> + void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12) + { + print(value1); + print(value2); + print(value3); + print(value4); + print(value5); + print(value6); + print(value7); + print(value8); + print(value9); + print(value10); + print(value11); + print(value12); + } + + template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13> + void print(const T1& value1, const T2& value2, const T3& value3, const T4& value4, const T5& value5, const T6& value6, const T7& value7, const T8& value8, const T9& value9, const T10& value10, const T11& value11, const T12& value12, const T13& value13) + { + print(value1); + print(value2); + print(value3); + print(value4); + print(value5); + print(value6); + print(value7); + print(value8); + print(value9); + print(value10); + print(value11); + print(value12); + print(value13); + } }; -void printInternal(PrintStream&, const char*); -void printInternal(PrintStream&, const CString&); -void printInternal(PrintStream&, const String&); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const char*); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const CString&); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&); inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); } inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); } inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); } -void printInternal(PrintStream&, bool); -void printInternal(PrintStream&, int); -void printInternal(PrintStream&, unsigned); -void printInternal(PrintStream&, long); -void printInternal(PrintStream&, unsigned long); -void printInternal(PrintStream&, long long); -void printInternal(PrintStream&, unsigned long long); -void printInternal(PrintStream&, float); -void printInternal(PrintStream&, double); -void printInternal(PrintStream&, RawPointer); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, int); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, long long); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, unsigned long long); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, float); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, double); +WTF_EXPORT_PRIVATE void printInternal(PrintStream&, RawPointer); template<typename T> void printInternal(PrintStream& out, const T& value) @@ -207,19 +258,47 @@ void printInternal(PrintStream& out, const T& value) m_value.method(out); \ } \ private: \ - Type m_value; \ + const Type& m_value; \ } +#define MAKE_PRINT_METHOD(Type, dumpMethod, method) \ + MAKE_PRINT_METHOD_ADAPTOR(DumperFor_##method, Type, dumpMethod); \ + DumperFor_##method method() const { return DumperFor_##method(*this); } + // Use an adaptor-based dumper for characters to avoid situations where // you've "compressed" an integer to a character and it ends up printing // as ASCII when you wanted it to print as a number. void dumpCharacter(PrintStream&, char); MAKE_PRINT_ADAPTOR(CharacterDump, char, dumpCharacter); +template<typename T> +class PointerDump { +public: + PointerDump(const T* ptr) + : m_ptr(ptr) + { + } + + void dump(PrintStream& out) const + { + if (m_ptr) + printInternal(out, *m_ptr); + else + out.print("(null)"); + } +private: + const T* m_ptr; +}; + +template<typename T> +PointerDump<T> pointerDump(const T* ptr) { return PointerDump<T>(ptr); } + } // namespace WTF using WTF::CharacterDump; +using WTF::PointerDump; using WTF::PrintStream; +using WTF::pointerDump; #endif // PrintStream_h diff --git a/Source/WTF/wtf/ProcessID.h b/Source/WTF/wtf/ProcessID.h new file mode 100644 index 000000000..f2d53932e --- /dev/null +++ b/Source/WTF/wtf/ProcessID.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 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 ProcessID_h +#define ProcessID_h + +#include <wtf/Platform.h> + +#if OS(UNIX) +#include <unistd.h> +#endif + +#if OS(WINDOWS) +#include <windows.h> +#endif + +namespace WTF { + +inline int getCurrentProcessID() +{ +#if OS(WINDOWS) + return GetCurrentProcessId(); +#else + return getpid(); +#endif +} + +} // namespace WTF + +using WTF::getCurrentProcessID; + +#endif // ProcessID_h + diff --git a/Source/WTF/wtf/RandomNumber.cpp b/Source/WTF/wtf/RandomNumber.cpp index 06074ed9f..7c764d3fc 100644 --- a/Source/WTF/wtf/RandomNumber.cpp +++ b/Source/WTF/wtf/RandomNumber.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2013 Andrew Bortz. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,42 +36,12 @@ #include <stdint.h> #include <stdlib.h> -#if USE(MERSENNE_TWISTER_19937) -extern "C" { -#include "mt19937ar.c" -} -#endif - namespace WTF { double randomNumber() { -#if USE(OS_RANDOMNESS) uint32_t bits = cryptographicallyRandomNumber(); return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#else - // Without OS_RANDOMNESS, we fall back to other random number generators - // that might not be cryptographically secure. Ideally, most ports would - // define USE(OS_RANDOMNESS). - -#if USE(MERSENNE_TWISTER_19937) - return genrand_res53(); -#else - uint32_t part1 = rand() & (RAND_MAX - 1); - uint32_t part2 = rand() & (RAND_MAX - 1); - // rand only provides 31 bits, and the low order bits of that aren't very random - // so we take the high 26 bits of part 1, and the high 27 bits of part2. - part1 >>= 5; // drop the low 5 bits - part2 >>= 4; // drop the low 4 bits - uint64_t fullRandom = part1; - fullRandom <<= 27; - fullRandom |= part2; - - // Mask off the low 53bits - fullRandom &= (1LL << 53) - 1; - return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); -#endif -#endif } } diff --git a/Source/WTF/wtf/RandomNumber.h b/Source/WTF/wtf/RandomNumber.h index 76b223582..fc5711423 100644 --- a/Source/WTF/wtf/RandomNumber.h +++ b/Source/WTF/wtf/RandomNumber.h @@ -28,9 +28,9 @@ namespace WTF { - // Returns a pseudo-random number in the range [0, 1), attempts to be - // cryptographically secure if possible on the target platform - WTF_EXPORT_PRIVATE double randomNumber(); +// Returns a pseudo-random number in the range [0, 1), attempts to be +// cryptographically secure if possible on the target platform +WTF_EXPORT_PRIVATE double randomNumber(); } diff --git a/Source/WTF/wtf/RandomNumberSeed.h b/Source/WTF/wtf/RandomNumberSeed.h index b5547becb..9290ec4ff 100644 --- a/Source/WTF/wtf/RandomNumberSeed.h +++ b/Source/WTF/wtf/RandomNumberSeed.h @@ -26,6 +26,7 @@ #ifndef WTF_RandomNumberSeed_h #define WTF_RandomNumberSeed_h +#include "RandomNumber.h" #include <stdlib.h> #include <time.h> @@ -38,13 +39,6 @@ #include <unistd.h> #endif -#if USE(MERSENNE_TWISTER_19937) -extern "C" { -void init_by_array(unsigned long init_key[],int key_length); -} -#endif - -// Internal JavaScriptCore usage only namespace WTF { inline void initializeRandomNumberGenerator() @@ -65,15 +59,6 @@ inline void initializeRandomNumberGenerator() srand(static_cast<unsigned>(time(0))); #endif -#if USE(MERSENNE_TWISTER_19937) - // use rand() to initialize the Mersenne Twister random number generator. - unsigned long initializationBuffer[4]; - initializationBuffer[0] = (rand() << 16) | rand(); - initializationBuffer[1] = (rand() << 16) | rand(); - initializationBuffer[2] = (rand() << 16) | rand(); - initializationBuffer[3] = (rand() << 16) | rand(); - init_by_array(initializationBuffer, 4); -#endif } } diff --git a/Source/WTF/wtf/RefCounted.h b/Source/WTF/wtf/RefCounted.h index 0504b9ed2..4d62bdfc8 100644 --- a/Source/WTF/wtf/RefCounted.h +++ b/Source/WTF/wtf/RefCounted.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,7 +26,6 @@ #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> #include <wtf/ThreadRestrictionVerifier.h> -#include <wtf/UnusedParam.h> namespace WTF { @@ -71,7 +70,7 @@ public: return m_refCount == 1; } - int refCount() const + unsigned refCount() const { #if CHECK_REF_COUNTED_LIFECYCLE ASSERT(m_verifier.isSafeToUse()); @@ -111,12 +110,6 @@ public: #endif } - // Helper for generating JIT code. Please do not use for non-JIT purposes. - const int* addressOfCount() const - { - return &m_refCount; - } - protected: RefCountedBase() : m_refCount(1) @@ -144,15 +137,16 @@ protected: ASSERT(!m_adoptionIsRequired); #endif - ASSERT(m_refCount > 0); - if (m_refCount == 1) { + ASSERT(m_refCount); + unsigned tempRefCount = m_refCount - 1; + if (!tempRefCount) { #if CHECK_REF_COUNTED_LIFECYCLE m_deletionHasBegun = true; #endif return true; } + m_refCount = tempRefCount; - --m_refCount; #if CHECK_REF_COUNTED_LIFECYCLE // Stop thread verification when the ref goes to 1 because it // is safe to be passed to another thread at this point. @@ -175,7 +169,7 @@ private: friend void adopted(RefCountedBase*); #endif - int m_refCount; + unsigned m_refCount; #if CHECK_REF_COUNTED_LIFECYCLE bool m_deletionHasBegun; bool m_adoptionIsRequired; diff --git a/Source/WTF/wtf/RefCountedArray.h b/Source/WTF/wtf/RefCountedArray.h index 289f1fc57..d0c183d83 100644 --- a/Source/WTF/wtf/RefCountedArray.h +++ b/Source/WTF/wtf/RefCountedArray.h @@ -57,7 +57,21 @@ public: if (m_data) Header::fromPayload(m_data)->refCount++; } - + + explicit RefCountedArray(size_t size) + { + if (!size) { + m_data = 0; + return; + } + + m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * size)))->payload(); + Header::fromPayload(m_data)->refCount = 1; + Header::fromPayload(m_data)->length = size; + ASSERT(Header::fromPayload(m_data)->length == size); + VectorTypeOperations<T>::initialize(begin(), end()); + } + explicit RefCountedArray(const Vector<T>& other) { if (other.isEmpty()) { @@ -69,7 +83,7 @@ public: Header::fromPayload(m_data)->refCount = 1; Header::fromPayload(m_data)->length = other.size(); ASSERT(Header::fromPayload(m_data)->length == other.size()); - memcpy(m_data, other.begin(), sizeof(T) * other.size()); + VectorTypeOperations<T>::uninitializedCopy(other.begin(), other.end(), m_data); } RefCountedArray& operator=(const RefCountedArray& other) @@ -83,6 +97,7 @@ public: return *this; if (--Header::fromPayload(oldData)->refCount) return *this; + VectorTypeOperations<T>::destruct(oldData, oldData + Header::fromPayload(oldData)->length); fastFree(Header::fromPayload(oldData)); return *this; } @@ -93,6 +108,7 @@ public: return; if (--Header::fromPayload(m_data)->refCount) return; + VectorTypeOperations<T>::destruct(begin(), end()); fastFree(Header::fromPayload(m_data)); } @@ -118,13 +134,13 @@ public: T& at(size_t i) { - ASSERT(i < size()); + ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return begin()[i]; } const T& at(size_t i) const { - ASSERT(i < size()); + ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return begin()[i]; } diff --git a/Source/WTF/wtf/RefCountedLeakCounter.h b/Source/WTF/wtf/RefCountedLeakCounter.h index 8d894dd91..48edd059a 100644 --- a/Source/WTF/wtf/RefCountedLeakCounter.h +++ b/Source/WTF/wtf/RefCountedLeakCounter.h @@ -38,7 +38,7 @@ namespace WTF { #ifndef NDEBUG private: -#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) +#if COMPILER(MINGW) || OS(WINCE) int m_count; #else volatile int m_count; diff --git a/Source/WTF/wtf/RefPtr.h b/Source/WTF/wtf/RefPtr.h index 322cbd6f8..2fa2251b8 100644 --- a/Source/WTF/wtf/RefPtr.h +++ b/Source/WTF/wtf/RefPtr.h @@ -24,6 +24,7 @@ #define WTF_RefPtr_h #include <algorithm> +#include <utility> #include <wtf/FastAllocBase.h> #include <wtf/PassRefPtr.h> @@ -43,6 +44,11 @@ namespace WTF { ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); } template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); } +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.release().leakRef()) { } + template<typename U> RefPtr(RefPtr<U>&& o) : m_ptr(o.release().leakRef()) { } +#endif + // See comments in PassRefPtr.h for an explanation of why this takes a const reference. template<typename U> RefPtr(const PassRefPtr<U>&); @@ -77,7 +83,10 @@ namespace WTF { #endif template<typename U> RefPtr& operator=(const RefPtr<U>&); template<typename U> RefPtr& operator=(const PassRefPtr<U>&); - +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + RefPtr& operator=(RefPtr&&); + template<typename U> RefPtr& operator=(RefPtr<U>&&); +#endif void swap(RefPtr&); static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } @@ -142,7 +151,21 @@ namespace WTF { derefIfNotNull(ptr); return *this; } +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr<T>&& o) + { + RefPtr<T> ptr = std::move(o); + swap(ptr); + return *this; + } + template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& o) + { + RefPtr<T> ptr = std::move(o); + swap(ptr); + return *this; + } +#endif template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o) { std::swap(m_ptr, o.m_ptr); diff --git a/Source/WTF/wtf/RetainPtr.h b/Source/WTF/wtf/RetainPtr.h index 71391fd09..26997283d 100644 --- a/Source/WTF/wtf/RetainPtr.h +++ b/Source/WTF/wtf/RetainPtr.h @@ -51,6 +51,11 @@ namespace WTF { enum AdoptNSTag { AdoptNS }; #ifdef __OBJC__ +#ifdef OBJC_NO_GC + inline void adoptNSReference(id) + { + } +#else inline void adoptNSReference(id ptr) { if (ptr) { @@ -59,6 +64,7 @@ namespace WTF { } } #endif +#endif template<typename T> class RetainPtr { public: @@ -68,8 +74,19 @@ namespace WTF { RetainPtr() : m_ptr(0) {} RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); } - RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { } - RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); } + RetainPtr(AdoptCFTag, PtrType ptr) + : m_ptr(ptr) + { +#ifdef __OBJC__ + static_assert((!std::is_convertible<T, id>::value), "Don't use adoptCF with Objective-C pointer types, use adoptNS."); +#endif + } + + RetainPtr(AdoptNSTag, PtrType ptr) + : m_ptr(ptr) + { + adoptNSReference(ptr); + } RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); } @@ -114,9 +131,6 @@ namespace WTF { RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } #endif - void adoptCF(PtrType); - void adoptNS(PtrType); - void swap(RetainPtr&); private: @@ -124,7 +138,7 @@ namespace WTF { PtrType m_ptr; }; - + template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { @@ -158,7 +172,7 @@ namespace WTF { CFRelease(ptr); return *this; } - + template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) { PtrType optr = o.get(); @@ -196,34 +210,23 @@ namespace WTF { #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o) { - adoptCF(o.leakRef()); - return *this; - } - - template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o) - { - adoptCF(o.leakRef()); - return *this; - } -#endif - - template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) - { PtrType ptr = m_ptr; - m_ptr = optr; + m_ptr = o.leakRef(); if (ptr) CFRelease(ptr); + + return *this; } - template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) + template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o) { - adoptNSReference(optr); - PtrType ptr = m_ptr; - m_ptr = optr; + m_ptr = o.leakRef(); if (ptr) CFRelease(ptr); + return *this; } +#endif template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) { @@ -297,6 +300,28 @@ namespace WTF { template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; }; + template <typename P> + struct RetainPtrObjectHashTraits : SimpleClassHashTraits<RetainPtr<P> > { + static const RetainPtr<P>& emptyValue() + { + static RetainPtr<P>& null = *(new RetainPtr<P>); + return null; + } + }; + + template <typename P> + struct RetainPtrObjectHash { + static unsigned hash(const RetainPtr<P>& o) + { + ASSERT_WITH_MESSAGE(o.get(), "attempt to use null RetainPtr in HashTable"); + return static_cast<unsigned>(CFHash(o.get())); + } + static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) + { + return CFEqual(a.get(), b.get()); + } + static const bool safeToCompareToEmptyOrDeleted = false; + }; } // namespace WTF using WTF::AdoptCF; diff --git a/Source/WTF/wtf/RunLoopTimer.h b/Source/WTF/wtf/RunLoopTimer.h new file mode 100644 index 000000000..6d21b3595 --- /dev/null +++ b/Source/WTF/wtf/RunLoopTimer.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RunLoopTimer_h +#define RunLoopTimer_h + +#include <wtf/SchedulePair.h> +#include <wtf/RetainPtr.h> + +namespace WTF { + +// Time intervals are all in seconds. + +class WTF_EXPORT_PRIVATE RunLoopTimerBase { + WTF_MAKE_NONCOPYABLE(RunLoopTimerBase); +public: + RunLoopTimerBase() { } + WTF_EXPORT_PRIVATE virtual ~RunLoopTimerBase(); + + WTF_EXPORT_PRIVATE void schedule(const SchedulePair*); + WTF_EXPORT_PRIVATE void schedule(const SchedulePairHashSet&); + + WTF_EXPORT_PRIVATE void start(double nextFireInterval, double repeatInterval); + + void startRepeating(double repeatInterval) { start(repeatInterval, repeatInterval); } + void startOneShot(double interval) { start(interval, 0); } + + WTF_EXPORT_PRIVATE void stop(); + bool isActive() const; + + virtual void fired() = 0; + +private: +#if USE(CF) + RetainPtr<CFRunLoopTimerRef> m_timer; +#endif +}; + +template <typename TimerFiredClass> class RunLoopTimer : public RunLoopTimerBase { +public: + typedef void (TimerFiredClass::*TimerFiredFunction)(RunLoopTimer*); + + RunLoopTimer(TimerFiredClass* o, TimerFiredFunction f) + : m_object(o), m_function(f) { } + + virtual void fired() { (m_object->*m_function)(this); } + +private: + TimerFiredClass* m_object; + TimerFiredFunction m_function; +}; + +} // namespace WTF + +using WTF::RunLoopTimer; + +#endif diff --git a/Source/WTF/wtf/RunLoopTimerCF.cpp b/Source/WTF/wtf/RunLoopTimerCF.cpp new file mode 100644 index 000000000..40b620f64 --- /dev/null +++ b/Source/WTF/wtf/RunLoopTimerCF.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if PLATFORM(MAC) && HAVE(RUNLOOP_TIMER) + +#include "RunLoopTimer.h" + +#include "AutodrainedPool.h" + +namespace WTF { + +RunLoopTimerBase::~RunLoopTimerBase() +{ + stop(); +} + +static void timerFired(CFRunLoopTimerRef, void* context) +{ + // CFRunLoopTimer does not create an NSAutoreleasePool, like NSTimer does. This can lead to + // autoreleased objects being pushed into NSAutoreleasePools underneath the run loop, which + // are very infrequently drained. Create a new autorelease pool here to give autoreleased objects + // a place to collect. + AutodrainedPool pool; + RunLoopTimerBase* timer = static_cast<RunLoopTimerBase*>(context); + timer->fired(); +} + +void RunLoopTimerBase::start(double nextFireInterval, double repeatInterval) +{ + if (m_timer) + CFRunLoopTimerInvalidate(m_timer.get()); + CFRunLoopTimerContext context = { 0, this, 0, 0, 0 }; + m_timer = adoptCF(CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context)); +} + +void RunLoopTimerBase::schedule(const SchedulePair* schedulePair) +{ + ASSERT_ARG(schedulePair, schedulePair); + ASSERT_WITH_MESSAGE(m_timer, "Timer must have one of the start functions called before calling schedule()."); + CFRunLoopAddTimer(schedulePair->runLoop(), m_timer.get(), schedulePair->mode()); +} + +void RunLoopTimerBase::schedule(const SchedulePairHashSet& schedulePairs) +{ + SchedulePairHashSet::const_iterator end = schedulePairs.end(); + for (SchedulePairHashSet::const_iterator it = schedulePairs.begin(); it != end; ++it) + schedule((*it).get()); +} + +void RunLoopTimerBase::stop() +{ + if (!m_timer) + return; + CFRunLoopTimerInvalidate(m_timer.get()); + m_timer = 0; +} + +bool RunLoopTimerBase::isActive() const +{ + return m_timer && CFRunLoopTimerIsValid(m_timer.get()); +} + +} // namespace WTF + +#endif // PLATFORM(MAC) && HAVE(RUNLOOP_TIMER) diff --git a/Source/WTF/wtf/SHA1.cpp b/Source/WTF/wtf/SHA1.cpp index 891c176eb..52b5529f1 100644 --- a/Source/WTF/wtf/SHA1.cpp +++ b/Source/WTF/wtf/SHA1.cpp @@ -42,34 +42,6 @@ namespace WTF { -#ifdef NDEBUG -static inline void testSHA1() { } -#else -static bool isTestSHA1Done; - -static void expectSHA1(CString input, int repeat, CString expected) -{ - SHA1 sha1; - for (int i = 0; i < repeat; ++i) - sha1.addBytes(input); - CString actual = sha1.computeHexDigest(); - ASSERT_WITH_MESSAGE(actual == expected, "input: %s, repeat: %d, actual: %s, expected: %s", input.data(), repeat, actual.data(), expected.data()); -} - -static void testSHA1() -{ - if (isTestSHA1Done) - return; - isTestSHA1Done = true; - - // Examples taken from sample code in RFC 3174. - expectSHA1("abc", 1, "A9993E364706816ABA3E25717850C26C9CD0D89D"); - expectSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); - expectSHA1("a", 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"); - expectSHA1("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); -} -#endif - static inline uint32_t f(int t, uint32_t b, uint32_t c, uint32_t d) { ASSERT(t >= 0 && t < 80); @@ -102,8 +74,6 @@ static inline uint32_t rotateLeft(int n, uint32_t x) SHA1::SHA1() { - // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. - testSHA1(); reset(); } diff --git a/Source/WTF/wtf/SchedulePair.h b/Source/WTF/wtf/SchedulePair.h new file mode 100644 index 000000000..fe1e18cf9 --- /dev/null +++ b/Source/WTF/wtf/SchedulePair.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SchedulePair_h +#define SchedulePair_h + +#include <wtf/HashSet.h> +#include <wtf/RefCounted.h> +#include <wtf/RetainPtr.h> +#include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> + +#if PLATFORM(MAC) +OBJC_CLASS NSRunLoop; +#endif + +namespace WTF { + +class SchedulePair : public RefCounted<SchedulePair> { +public: + static PassRefPtr<SchedulePair> create(CFRunLoopRef runLoop, CFStringRef mode) { return adoptRef(new SchedulePair(runLoop, mode)); } + +#if PLATFORM(MAC) && !USE(CFNETWORK) + static PassRefPtr<SchedulePair> create(NSRunLoop* runLoop, CFStringRef mode) { return adoptRef(new SchedulePair(runLoop, mode)); } + NSRunLoop* nsRunLoop() const { return m_nsRunLoop.get(); } +#endif + + CFRunLoopRef runLoop() const { return m_runLoop.get(); } + CFStringRef mode() const { return m_mode.get(); } + + WTF_EXPORT_PRIVATE bool operator==(const SchedulePair& other) const; + +private: + SchedulePair(CFRunLoopRef runLoop, CFStringRef mode) + : m_runLoop(runLoop) + { + if (mode) + m_mode = adoptCF(CFStringCreateCopy(0, mode)); + } + +#if PLATFORM(MAC) && !USE(CFNETWORK) + WTF_EXPORT_PRIVATE SchedulePair(NSRunLoop*, CFStringRef); + RetainPtr<NSRunLoop*> m_nsRunLoop; +#endif + + RetainPtr<CFRunLoopRef> m_runLoop; + RetainPtr<CFStringRef> m_mode; +}; + +struct SchedulePairHash { + static unsigned hash(const RefPtr<SchedulePair>& pair) + { + uintptr_t hashCodes[2] = { reinterpret_cast<uintptr_t>(pair->runLoop()), pair->mode() ? CFHash(pair->mode()) : 0 }; + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); + } + + static bool equal(const RefPtr<SchedulePair>& a, const RefPtr<SchedulePair>& b) { return a == b; } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +typedef HashSet<RefPtr<SchedulePair>, SchedulePairHash> SchedulePairHashSet; + +} // namespace WTF + +using WTF::SchedulePair; +using WTF::SchedulePairHashSet; + +#endif diff --git a/Source/WTF/wtf/SchedulePairCF.cpp b/Source/WTF/wtf/SchedulePairCF.cpp new file mode 100644 index 000000000..f761a22b5 --- /dev/null +++ b/Source/WTF/wtf/SchedulePairCF.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SchedulePair.h" + +namespace WTF { + +bool SchedulePair::operator==(const SchedulePair& other) const +{ + if (runLoop() != other.runLoop()) + return false; + CFStringRef thisMode = mode(); + CFStringRef otherMode = other.mode(); + if (!thisMode || !otherMode) + return thisMode == otherMode; + return CFEqual(thisMode, otherMode); +} + +} // namespace diff --git a/Source/WTF/wtf/Complex.h b/Source/WTF/wtf/SchedulePairMac.mm index 40fe56a7b..dc58aa08d 100644 --- a/Source/WTF/wtf/Complex.h +++ b/Source/WTF/wtf/SchedulePairMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,24 +26,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WTF_Complex_h -#define WTF_Complex_h +#include "config.h" +#include "SchedulePair.h" -#include <complex> -#include <wtf/MathExtras.h> +#if !USE(CFNETWORK) namespace WTF { -typedef std::complex<double> Complex; - -inline Complex complexFromMagnitudePhase(double magnitude, double phase) +SchedulePair::SchedulePair(NSRunLoop* runLoop, CFStringRef mode) + : m_nsRunLoop(runLoop) + , m_runLoop([runLoop getCFRunLoop]) { - return Complex(magnitude * cos(phase), magnitude * sin(phase)); + if (mode) + m_mode = adoptCF(CFStringCreateCopy(0, mode)); } -} // namespace WTF - -using WTF::Complex; -using WTF::complexFromMagnitudePhase; +} // namespace -#endif // WTF_Complex_h +#endif diff --git a/Source/WTF/wtf/SegmentedVector.h b/Source/WTF/wtf/SegmentedVector.h index 63d89d7ab..048aa5366 100644 --- a/Source/WTF/wtf/SegmentedVector.h +++ b/Source/WTF/wtf/SegmentedVector.h @@ -29,6 +29,7 @@ #ifndef SegmentedVector_h #define SegmentedVector_h +#include <wtf/Noncopyable.h> #include <wtf/Vector.h> namespace WTF { @@ -104,13 +105,14 @@ namespace WTF { template <typename T, size_t SegmentSize, size_t InlineCapacity> class SegmentedVector { friend class SegmentedVectorIterator<T, SegmentSize, InlineCapacity>; + WTF_MAKE_NONCOPYABLE(SegmentedVector); + public: typedef SegmentedVectorIterator<T, SegmentSize, InlineCapacity> Iterator; SegmentedVector() : m_size(0) { - m_segments.append(&m_inlineSegment); } ~SegmentedVector() @@ -123,16 +125,24 @@ namespace WTF { T& at(size_t index) { - if (index < SegmentSize) - return m_inlineSegment[index]; return segmentFor(index)->at(subscriptFor(index)); } + const T& at(size_t index) const + { + return const_cast<SegmentedVector<T, SegmentSize, InlineCapacity>*>(this)->at(index); + } + T& operator[](size_t index) { return at(index); } + const T& operator[](size_t index) const + { + return at(index); + } + T& last() { return at(size() - 1); @@ -142,11 +152,6 @@ namespace WTF { { ++m_size; - if (m_size <= SegmentSize) { - m_inlineSegment.uncheckedAppend(value); - return; - } - if (!segmentExistsFor(m_size - 1)) m_segments.append(new Segment); segmentFor(m_size - 1)->uncheckedAppend(value); @@ -160,10 +165,7 @@ namespace WTF { void removeLast() { - if (m_size <= SegmentSize) - m_inlineSegment.removeLast(); - else - segmentFor(m_size - 1)->removeLast(); + segmentFor(m_size - 1)->removeLast(); --m_size; } @@ -177,8 +179,7 @@ namespace WTF { void clear() { deleteAllSegments(); - m_segments.resize(1); - m_inlineSegment.clear(); + m_segments.clear(); m_size = 0; } @@ -202,9 +203,7 @@ namespace WTF { void deleteAllSegments() { - // Skip the first segment, because it's our inline segment, which was - // not created by new. - for (size_t i = 1; i < m_segments.size(); i++) + for (size_t i = 0; i < m_segments.size(); i++) delete m_segments[i]; } @@ -225,18 +224,12 @@ namespace WTF { void ensureSegmentsFor(size_t size) { - size_t segmentCount = m_size / SegmentSize; - if (m_size % SegmentSize) - ++segmentCount; - segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment. - - size_t neededSegmentCount = size / SegmentSize; - if (size % SegmentSize) - ++neededSegmentCount; + size_t segmentCount = (m_size + SegmentSize - 1) / SegmentSize; + size_t neededSegmentCount = (size + SegmentSize - 1) / SegmentSize; // Fill up to N - 1 segments. size_t end = neededSegmentCount - 1; - for (size_t i = segmentCount - 1; i < end; ++i) + for (size_t i = segmentCount ? segmentCount - 1 : 0; i < end; ++i) ensureSegment(i, SegmentSize); // Grow segment N to accomodate the remainder. @@ -245,15 +238,14 @@ namespace WTF { void ensureSegment(size_t segmentIndex, size_t size) { - ASSERT(segmentIndex <= m_segments.size()); + ASSERT_WITH_SECURITY_IMPLICATION(segmentIndex <= m_segments.size()); if (segmentIndex == m_segments.size()) m_segments.append(new Segment); m_segments[segmentIndex]->grow(size); } size_t m_size; - Segment m_inlineSegment; - Vector<Segment*, InlineCapacity> m_segments; + Vector<Segment*> m_segments; }; } // namespace WTF diff --git a/Source/WTF/wtf/SizeLimits.cpp b/Source/WTF/wtf/SizeLimits.cpp index 95d9c2b1e..cb2d60b78 100644 --- a/Source/WTF/wtf/SizeLimits.cpp +++ b/Source/WTF/wtf/SizeLimits.cpp @@ -60,6 +60,7 @@ COMPILE_ASSERT(sizeof(PassRefPtr<RefCounted<int> >) == sizeof(int*), PassRefPtr_ COMPILE_ASSERT(sizeof(RefCounted<int>) == sizeof(SameSizeAsRefCounted), RefCounted_should_stay_small); COMPILE_ASSERT(sizeof(RefCountedCustomAllocated<int>) == sizeof(SameSizeAsRefCounted), RefCountedCustomAllocated_should_stay_small); COMPILE_ASSERT(sizeof(RefPtr<RefCounted<int> >) == sizeof(int*), RefPtr_should_stay_small); -COMPILE_ASSERT(sizeof(Vector<int>) == 3 * sizeof(int*), Vector_should_stay_small); +COMPILE_ASSERT(sizeof(Vector<int>) == sizeof(int*) + 2 * sizeof(int), Vector_should_stay_small); +COMPILE_ASSERT(sizeof(Vector<int, 1>) == 2 * sizeof(int*) + 2 * sizeof(int), Vector_should_stay_small); } diff --git a/Source/WTF/wtf/StackBounds.cpp b/Source/WTF/wtf/StackBounds.cpp index a272ce3de..62e2665a4 100644 --- a/Source/WTF/wtf/StackBounds.cpp +++ b/Source/WTF/wtf/StackBounds.cpp @@ -55,31 +55,23 @@ namespace WTF { -// Bug 26276 - Need a mechanism to determine stack extent -// -// These platforms should now be working correctly: -// DARWIN, QNX, UNIX -// These platforms are not: -// WINDOWS, SOLARIS, OPENBSD, WINCE -// -// FIXME: remove this! - this code unsafely guesses at stack sizes! -#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD) -// Based on the current limit used by the JSC parser, guess the stack size. -static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024; -// This method assumes the stack is growing downwards. -static void* estimateStackBound(void* origin) -{ - return static_cast<char*>(origin) - estimatedStackSize; -} -#endif - #if OS(DARWIN) void StackBounds::initialize() { pthread_t thread = pthread_self(); m_origin = pthread_get_stackaddr_np(thread); - m_bound = static_cast<char*>(m_origin) - pthread_get_stacksize_np(thread); + rlim_t size = 0; + if (pthread_main_np()) { + // FIXME: <rdar://problem/13741204> + // pthread_get_size lies to us when we're the main thread, use get_rlimit instead + rlimit limit; + getrlimit(RLIMIT_STACK, &limit); + size = limit.rlim_cur; + } else + size = pthread_get_stacksize_np(thread); + + m_bound = static_cast<char*>(m_origin) - size; } #elif OS(QNX) @@ -114,7 +106,7 @@ void StackBounds::initialize() stack_t s; thr_stksegment(&s); m_origin = s.ss_sp; - m_bound = estimateStackBound(m_origin); + m_bound = static_cast<char*>(m_origin) - s.ss_size; } #elif OS(OPENBSD) @@ -125,7 +117,11 @@ void StackBounds::initialize() stack_t stack; pthread_stackseg_np(thread, &stack); m_origin = stack.ss_sp; - m_bound = estimateStackBound(m_origin); +#if CPU(HPPA) + m_bound = static_cast<char*>(m_origin) + stack.ss_size; +#else + m_bound = static_cast<char*>(m_origin) - stack.ss_size; +#endif } #elif OS(UNIX) @@ -153,105 +149,65 @@ void StackBounds::initialize() m_origin = static_cast<char*>(stackBase) + stackSize; } -#elif OS(WINCE) - -static bool detectGrowingDownward(void* previousFrame) -{ - // Find the address of this stack frame by taking the address of a local variable. - int thisFrame; - return previousFrame > &thisFrame; -} - -static inline bool isPageWritable(void* page) -{ - MEMORY_BASIC_INFORMATION memoryInformation; - DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation)); - - // return false on error, including ptr outside memory - if (result != sizeof(memoryInformation)) - return false; - - DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE); - return protect == PAGE_READWRITE - || protect == PAGE_WRITECOPY - || protect == PAGE_EXECUTE_READWRITE - || protect == PAGE_EXECUTE_WRITECOPY; -} - -static inline void* getLowerStackBound(char* currentPage, DWORD pageSize) -{ - while (currentPage > 0) { - // check for underflow - if (currentPage >= reinterpret_cast<char*>(pageSize)) - currentPage -= pageSize; - else - currentPage = 0; - - if (!isPageWritable(currentPage)) - return currentPage + pageSize; - } - - return 0; -} - -static inline void* getUpperStackBound(char* currentPage, DWORD pageSize) -{ - do { - // guaranteed to complete because isPageWritable returns false at end of memory - currentPage += pageSize; - } while (isPageWritable(currentPage)); - - return currentPage - pageSize; -} +#elif OS(WINDOWS) void StackBounds::initialize() { - // find the address of this stack frame by taking the address of a local variable - void* thisFrame = &thisFrame; - bool isGrowingDownward = detectGrowingDownward(thisFrame); + MEMORY_BASIC_INFORMATION stackOrigin; + VirtualQuery(&stackOrigin, &stackOrigin, sizeof(stackOrigin)); + // stackOrigin.AllocationBase points to the reserved stack memory base address. + m_origin = static_cast<char*>(stackOrigin.BaseAddress) + stackOrigin.RegionSize; +#if OS(WINCE) SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); DWORD pageSize = systemInfo.dwPageSize; - // scan all of memory starting from this frame, and return the last writeable page found - char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1)); - void* lowerStackBound = getLowerStackBound(currentPage, pageSize); - void* upperStackBound = getUpperStackBound(currentPage, pageSize); + MEMORY_BASIC_INFORMATION stackMemory; + VirtualQuery(m_origin, &stackMemory, sizeof(stackMemory)); - m_origin = isGrowingDownward ? upperStackBound : lowerStackBound; - m_bound = isGrowingDownward ? lowerStackBound : upperStackBound; -} - -#elif OS(WINDOWS) - -void StackBounds::initialize() -{ -#if CPU(X86) && COMPILER(MSVC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - __asm { - MOV EAX, FS:[18h] - MOV pTib, EAX - } - m_origin = static_cast<void*>(pTib->StackBase); -#elif CPU(X86) && COMPILER(GCC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - asm ( "movl %%fs:0x18, %0\n" - : "=r" (pTib) - ); - m_origin = static_cast<void*>(pTib->StackBase); -#elif CPU(X86_64) - PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); - m_origin = reinterpret_cast<void*>(pTib->StackBase); + m_bound = static_cast<char*>(m_origin) - stackMemory.RegionSize + pageSize; #else -#error Need a way to get the stack bounds on this platform (Windows) -#endif - // Looks like we should be able to get pTib->StackLimit - m_bound = estimateStackBound(m_origin); + // The stack on Windows consists out of three parts (uncommitted memory, a guard page and present + // committed memory). The 3 regions have different BaseAddresses but all have the same AllocationBase + // since they are all from the same VirtualAlloc. The 3 regions are laid out in memory (from high to + // low) as follows: + // + // High |-------------------| ----- + // | committedMemory | ^ + // |-------------------| | + // | guardPage | reserved memory for the stack + // |-------------------| | + // | uncommittedMemory | v + // Low |-------------------| ----- <--- stackOrigin.AllocationBase + // + // See http://msdn.microsoft.com/en-us/library/ms686774%28VS.85%29.aspx for more information. + + MEMORY_BASIC_INFORMATION uncommittedMemory; + VirtualQuery(stackOrigin.AllocationBase, &uncommittedMemory, sizeof(uncommittedMemory)); + ASSERT(uncommittedMemory.State == MEM_RESERVE); + + MEMORY_BASIC_INFORMATION guardPage; + VirtualQuery(static_cast<char*>(uncommittedMemory.BaseAddress) + uncommittedMemory.RegionSize, &guardPage, sizeof(guardPage)); + ASSERT(guardPage.Protect & PAGE_GUARD); + + void* endOfStack = stackOrigin.AllocationBase; + +#ifndef NDEBUG + MEMORY_BASIC_INFORMATION committedMemory; + VirtualQuery(static_cast<char*>(guardPage.BaseAddress) + guardPage.RegionSize, &committedMemory, sizeof(committedMemory)); + ASSERT(committedMemory.State == MEM_COMMIT); + + void* computedEnd = static_cast<char*>(m_origin) - (uncommittedMemory.RegionSize + guardPage.RegionSize + committedMemory.RegionSize); + + ASSERT(stackOrigin.AllocationBase == uncommittedMemory.AllocationBase); + ASSERT(stackOrigin.AllocationBase == guardPage.AllocationBase); + ASSERT(stackOrigin.AllocationBase == committedMemory.AllocationBase); + ASSERT(stackOrigin.AllocationBase == uncommittedMemory.BaseAddress); + ASSERT(endOfStack == computedEnd); +#endif // NDEBUG + m_bound = static_cast<char*>(endOfStack) + guardPage.RegionSize; +#endif // OS(WINCE) } #else diff --git a/Source/WTF/wtf/StackBounds.h b/Source/WTF/wtf/StackBounds.h index 185afec22..a595c1b2f 100644 --- a/Source/WTF/wtf/StackBounds.h +++ b/Source/WTF/wtf/StackBounds.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All Rights Reserved. + * Copyright (C) 2010, 2013 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,12 +41,6 @@ class StackBounds { const static size_t s_defaultAvailabilityDelta = 64 * 1024; public: - StackBounds() - : m_origin(0) - , m_bound(0) - { - } - static StackBounds currentThreadStackBounds() { StackBounds bounds; @@ -55,46 +49,51 @@ public: return bounds; } + bool isSafeToRecurse(size_t minAvailableDelta = s_defaultAvailabilityDelta) const + { + checkConsistency(); + if (isGrowingDownward()) + return current() >= recursionLimit(minAvailableDelta); + return current() <= recursionLimit(minAvailableDelta); + } + void* origin() const { ASSERT(m_origin); return m_origin; } - void* current() const + size_t size() const { - checkConsistency(); - void* currentPosition = ¤tPosition; - return currentPosition; + if (isGrowingDownward()) + return static_cast<char*>(m_origin) - static_cast<char*>(m_bound); + return static_cast<char*>(m_bound) - static_cast<char*>(m_origin); } - size_t size() const +private: + StackBounds() + : m_origin(0) + , m_bound(0) { - return isGrowingDownward() - ? static_cast<char*>(m_origin) - static_cast<char*>(m_bound) - : static_cast<char*>(m_bound) - static_cast<char*>(m_origin); } - void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const + WTF_EXPORT_PRIVATE void initialize(); + + void* current() const { checkConsistency(); - return isGrowingDownward() - ? static_cast<char*>(m_bound) + minAvailableDelta - : static_cast<char*>(m_bound) - minAvailableDelta; + void* currentPosition = ¤tPosition; + return currentPosition; } - bool isSafeToRecurse(size_t minAvailableDelta = s_defaultAvailabilityDelta) const + void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const { checkConsistency(); - return isGrowingDownward() - ? current() >= recursionLimit(minAvailableDelta) - : current() <= recursionLimit(minAvailableDelta); + if (isGrowingDownward()) + return static_cast<char*>(m_bound) + minAvailableDelta; + return static_cast<char*>(m_bound) - minAvailableDelta; } -private: - void initialize(); - - bool isGrowingDownward() const { ASSERT(m_origin && m_bound); diff --git a/Source/WTF/wtf/StaticConstructors.h b/Source/WTF/wtf/StaticConstructors.h index 702c0ca5c..23e403803 100644 --- a/Source/WTF/wtf/StaticConstructors.h +++ b/Source/WTF/wtf/StaticConstructors.h @@ -51,24 +51,14 @@ #ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC // Define an global in the normal way. -#if COMPILER(MSVC7_OR_LOWER) -#define DEFINE_GLOBAL(type, name) \ - const type name; -#else #define DEFINE_GLOBAL(type, name, ...) \ const type name; -#endif #else // Define an correctly-sized array of pointers to avoid static initialization. // Use an array of pointers instead of an array of char in case there is some alignment issue. -#if COMPILER(MSVC7_OR_LOWER) -#define DEFINE_GLOBAL(type, name) \ - void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; -#else #define DEFINE_GLOBAL(type, name, ...) \ void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; #endif -#endif #endif // StaticConstructors_h diff --git a/Source/WTF/wtf/StdLibExtras.h b/Source/WTF/wtf/StdLibExtras.h index 39578515b..e4dbe7cdb 100644 --- a/Source/WTF/wtf/StdLibExtras.h +++ b/Source/WTF/wtf/StdLibExtras.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2013 Patrick Gansterer <paroga@paroga.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -178,128 +179,113 @@ template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x) enum BinarySearchMode { KeyMustBePresentInArray, - KeyMustNotBePresentInArray + KeyMightNotBePresentInArray, + ReturnAdjacentElementIfKeyIsNotPresent }; -// Binary search algorithm, calls extractKey on pre-sorted elements in array, -// compares result with key (KeyTypes should be comparable with '==', and '<'). -template<typename ArrayElementType, typename KeyType, KeyType(*extractKey)(ArrayElementType*)> -inline ArrayElementType* binarySearch(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray) +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey, BinarySearchMode mode> +inline ArrayElementType* binarySearchImpl(ArrayType& array, size_t size, KeyType key, const ExtractKey& extractKey = ExtractKey()) { - // The array must contain at least one element (pre-condition, array does contain key). - // If the array contains only one element, no need to do the comparison. + size_t offset = 0; while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[pos]); - - // If the key matches, success! + size_t pos = (size - 1) >> 1; + KeyType val = extractKey(&array[offset + pos]); + if (val == key) - return &array[pos]; + return &array[offset + pos]; // The item we are looking for is smaller than the item being check; reduce the value of 'size', // chopping off the right hand half of the array. - else if (key < val) + if (key < val) size = pos; // Discard all values in the left hand half of the array, up to and including the item at pos. else { size -= (pos + 1); - array += (pos + 1); + offset += (pos + 1); } - // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. - if (mode == KeyMustBePresentInArray) - ASSERT(size); + ASSERT(mode != KeyMustBePresentInArray || size); } + + if (mode == KeyMightNotBePresentInArray && !size) + return 0; + + ArrayElementType* result = &array[offset]; + + if (mode == KeyMightNotBePresentInArray && key != extractKey(result)) + return 0; - // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point - // we've chopped down to one element, no need to check it matches if (mode == KeyMustBePresentInArray) { ASSERT(size == 1); - ASSERT(key == extractKey(&array[0])); + ASSERT(key == extractKey(result)); } - return &array[0]; + return result; } -// Modified binary search algorithm that uses a functor. Note that this is strictly -// more powerful than the above, but results in somewhat less template specialization. -// Hence, depending on inlining heuristics, it might be slower. -template<typename ArrayElementType, typename KeyType, typename ExtractKey> -inline ArrayElementType* binarySearchWithFunctor(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray, const ExtractKey& extractKey = ExtractKey()) +// If the element is not found, crash if asserts are enabled, and behave like approximateBinarySearch in release builds. +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* binarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) { - // The array must contain at least one element (pre-condition, array does contain key). - // If the array contains only one element, no need to do the comparison. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[pos]); - - // If the key matches, success! - if (val == key) - return &array[pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - else if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - array += (pos + 1); - } - - // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. - if (mode == KeyMustBePresentInArray) - ASSERT(size); - } + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMustBePresentInArray>(array, size, key, extractKey); +} - // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point - // we've chopped down to one element, no need to check it matches - if (mode == KeyMustBePresentInArray) { - ASSERT(size == 1); - ASSERT(key == extractKey(&array[0])); - } +// Return zero if the element is not found. +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* tryBinarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) +{ + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMightNotBePresentInArray>(array, size, key, extractKey); +} - return &array[0]; +// Return the element that is either to the left, or the right, of where the element would have been found. +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* approximateBinarySearch(ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) +{ + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, ReturnAdjacentElementIfKeyIsNotPresent>(array, size, key, extractKey); } -// Modified binarySearch() algorithm designed for array-like classes that support -// operator[] but not operator+=. One example of a class that qualifies is -// SegmentedVector. -template<typename ArrayElementType, typename KeyType, KeyType(*extractKey)(ArrayElementType*), typename ArrayType> -inline ArrayElementType* genericBinarySearch(ArrayType& array, size_t size, KeyType key) +// Variants of the above that use const. +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* binarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) { - // The array must contain at least one element (pre-condition, array does conatin key). - // If the array only contains one element, no need to do the comparison. - size_t offset = 0; - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[offset + pos]); - - // If the key matches, success! - if (val == key) - return &array[offset + pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - offset += (pos + 1); - } + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMustBePresentInArray>(const_cast<ArrayType&>(array), size, key, extractKey); +} +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* tryBinarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) +{ + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, KeyMightNotBePresentInArray>(const_cast<ArrayType&>(array), size, key, extractKey); +} +template<typename ArrayElementType, typename KeyType, typename ArrayType, typename ExtractKey> +inline ArrayElementType* approximateBinarySearch(const ArrayType& array, size_t size, KeyType key, ExtractKey extractKey = ExtractKey()) +{ + return binarySearchImpl<ArrayElementType, KeyType, ArrayType, ExtractKey, ReturnAdjacentElementIfKeyIsNotPresent>(const_cast<ArrayType&>(array), size, key, extractKey); +} - // 'size' should never reach zero. - ASSERT(size); +} // namespace WTF + +#if OS(WINCE) +// Windows CE CRT has does not implement bsearch(). +inline void* wtf_bsearch(const void* key, const void* base, size_t count, size_t size, int (*compare)(const void *, const void *)) +{ + const char* first = static_cast<const char*>(base); + + while (count) { + size_t pos = (count - 1) >> 1; + const char* item = first + pos * size; + int compareResult = compare(item, key); + if (!compareResult) + return const_cast<char*>(item); + if (compareResult < 0) { + count -= (pos + 1); + first += (pos + 1) * size; + } else + count = pos; } - - // If we reach this point we've chopped down to one element, no need to check it matches - ASSERT(size == 1); - ASSERT(key == extractKey(&array[offset])); - return &array[offset]; + + return 0; } -} // namespace WTF +#define bsearch(key, base, count, size, compare) wtf_bsearch(key, base, count, size, compare) +#endif // This version of placement new omits a 0 check. enum NotNullTag { NotNull }; @@ -314,6 +300,8 @@ using WTF::MB; using WTF::isPointerAligned; using WTF::is8ByteAligned; using WTF::binarySearch; +using WTF::tryBinarySearch; +using WTF::approximateBinarySearch; using WTF::bitwise_cast; using WTF::safeCast; diff --git a/Source/WTF/wtf/StreamBuffer.h b/Source/WTF/wtf/StreamBuffer.h index e7d958f69..990b8121f 100644 --- a/Source/WTF/wtf/StreamBuffer.h +++ b/Source/WTF/wtf/StreamBuffer.h @@ -32,7 +32,6 @@ #define WTF_StreamBuffer_h #include <wtf/Deque.h> -#include <wtf/FixedArray.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> diff --git a/Source/WTF/wtf/StringExtras.h b/Source/WTF/wtf/StringExtras.h index 371e33bf9..eaf0cf76a 100644 --- a/Source/WTF/wtf/StringExtras.h +++ b/Source/WTF/wtf/StringExtras.h @@ -116,11 +116,4 @@ inline char* strnstr(const char* buffer, const char* target, size_t bufferLength #endif -#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 - -int strcasecmp(const char* s1, const char* s2); -int strncasecmp(const char* s1, const char* s2, size_t len); - -#endif - #endif // WTF_StringExtras_h diff --git a/Source/WTF/wtf/StringHasher.h b/Source/WTF/wtf/StringHasher.h index 53b1b5443..d9582aa94 100644 --- a/Source/WTF/wtf/StringHasher.h +++ b/Source/WTF/wtf/StringHasher.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2008, 2010, 2013 Apple Inc. All rights reserved. * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> * * This library is free software; you can redistribute it and/or @@ -18,6 +18,7 @@ * Boston, MA 02110-1301, USA. * */ + #ifndef WTF_StringHasher_h #define WTF_StringHasher_h @@ -25,51 +26,144 @@ namespace WTF { -// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's -static const unsigned stringHashingStartValue = 0x9e3779b9U; - // Paul Hsieh's SuperFastHash // http://www.azillionmonkeys.com/qed/hash.html -// char* data is interpreted as latin-encoded (zero extended to 16 bits). -// NOTE: This class must stay in sync with the create_hash_table script in +// LChar data is interpreted as Latin-1-encoded (zero extended to 16 bits). + +// NOTE: The hash computation here must stay in sync with the create_hash_table script in // JavaScriptCore and the CodeGeneratorJS.pm script in WebCore. + +// Golden ratio. Arbitrary start value to avoid mapping all zeros to a hash value of zero. +static const unsigned stringHashingStartValue = 0x9E3779B9U; + class StringHasher { public: static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags. - inline StringHasher() + StringHasher() : m_hash(stringHashingStartValue) , m_hasPendingCharacter(false) , m_pendingCharacter(0) { } - inline void addCharacters(UChar a, UChar b) + // The hasher hashes two characters at a time, and thus an "aligned" hasher is one + // where an even number of characters have been added. Callers that always add + // characters two at a time can use the "assuming aligned" functions. + void addCharactersAssumingAligned(UChar a, UChar b) { ASSERT(!m_hasPendingCharacter); - addCharactersToHash(a, b); + m_hash += a; + m_hash = (m_hash << 16) ^ ((b << 11) ^ m_hash); + m_hash += m_hash >> 11; } - inline void addCharacter(UChar ch) + void addCharacter(UChar character) { if (m_hasPendingCharacter) { - addCharactersToHash(m_pendingCharacter, ch); m_hasPendingCharacter = false; + addCharactersAssumingAligned(m_pendingCharacter, character); return; } - m_pendingCharacter = ch; + m_pendingCharacter = character; m_hasPendingCharacter = true; } - inline unsigned hashWithTop8BitsMasked() const + void addCharacters(UChar a, UChar b) + { + if (m_hasPendingCharacter) { +#if !ASSERT_DISABLED + m_hasPendingCharacter = false; +#endif + addCharactersAssumingAligned(m_pendingCharacter, a); + m_pendingCharacter = b; +#if !ASSERT_DISABLED + m_hasPendingCharacter = true; +#endif + return; + } + + addCharactersAssumingAligned(a, b); + } + + template<typename T, UChar Converter(T)> void addCharactersAssumingAligned(const T* data, unsigned length) + { + ASSERT(!m_hasPendingCharacter); + + bool remainder = length & 1; + length >>= 1; + + while (length--) { + addCharactersAssumingAligned(Converter(data[0]), Converter(data[1])); + data += 2; + } + + if (remainder) + addCharacter(Converter(*data)); + } + + template<typename T> void addCharactersAssumingAligned(const T* data, unsigned length) + { + addCharactersAssumingAligned<T, defaultConverter>(data, length); + } + + template<typename T, UChar Converter(T)> void addCharactersAssumingAligned(const T* data) + { + ASSERT(!m_hasPendingCharacter); + + while (T a = *data++) { + T b = *data++; + if (!b) { + addCharacter(Converter(a)); + break; + } + addCharactersAssumingAligned(Converter(a), Converter(b)); + } + } + + template<typename T> void addCharactersAssumingAligned(const T* data) + { + addCharactersAssumingAligned<T, defaultConverter>(data); + } + + template<typename T, UChar Converter(T)> void addCharacters(const T* data, unsigned length) + { + if (m_hasPendingCharacter && length) { + m_hasPendingCharacter = false; + addCharactersAssumingAligned(m_pendingCharacter, Converter(*data++)); + --length; + } + addCharactersAssumingAligned<T, Converter>(data, length); + } + + template<typename T> void addCharacters(const T* data, unsigned length) + { + addCharacters<T, defaultConverter>(data, length); + } + + template<typename T, UChar Converter(T)> void addCharacters(const T* data) + { + if (m_hasPendingCharacter && *data) { + m_hasPendingCharacter = false; + addCharactersAssumingAligned(m_pendingCharacter, Converter(*data++)); + } + addCharactersAssumingAligned<T, Converter>(data); + } + + template<typename T> void addCharacters(const T* data) + { + addCharacters<T, defaultConverter>(data); + } + + unsigned hashWithTop8BitsMasked() const { unsigned result = avalancheBits(); // Reserving space from the high bits for flags preserves most of the hash's // value, since hash lookup typically masks out the high bits anyway. - result &= (1u << (sizeof(result) * 8 - flagCount)) - 1; + result &= (1U << (sizeof(result) * 8 - flagCount)) - 1; // This avoids ever returning a hash code of 0, since that is used to // signal "hash not computed yet". Setting the high bit maintains @@ -81,7 +175,7 @@ public: return result; } - inline unsigned hash() const + unsigned hash() const { unsigned result = avalancheBits(); @@ -95,132 +189,81 @@ public: return result; } - template<typename T, UChar Converter(T)> static inline unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) + template<typename T, UChar Converter(T)> static unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) { StringHasher hasher; - bool rem = length & 1; - length >>= 1; - - while (length--) { - hasher.addCharacters(Converter(data[0]), Converter(data[1])); - data += 2; - } - - if (rem) - hasher.addCharacter(Converter(*data)); - + hasher.addCharactersAssumingAligned<T, Converter>(data, length); return hasher.hashWithTop8BitsMasked(); } - template<typename T, UChar Converter(T)> static inline unsigned computeHashAndMaskTop8Bits(const T* data) + template<typename T, UChar Converter(T)> static unsigned computeHashAndMaskTop8Bits(const T* data) { StringHasher hasher; - - while (true) { - UChar b0 = Converter(*data++); - if (!b0) - break; - UChar b1 = Converter(*data++); - if (!b1) { - hasher.addCharacter(b0); - break; - } - - hasher.addCharacters(b0, b1); - } - + hasher.addCharactersAssumingAligned<T, Converter>(data); return hasher.hashWithTop8BitsMasked(); } - template<typename T> static inline unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) + template<typename T> static unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) { return computeHashAndMaskTop8Bits<T, defaultConverter>(data, length); } - template<typename T> static inline unsigned computeHashAndMaskTop8Bits(const T* data) + template<typename T> static unsigned computeHashAndMaskTop8Bits(const T* data) { return computeHashAndMaskTop8Bits<T, defaultConverter>(data); } - template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data, unsigned length) + template<typename T, UChar Converter(T)> static unsigned computeHash(const T* data, unsigned length) { StringHasher hasher; - bool rem = length & 1; - length >>= 1; - - while (length--) { - hasher.addCharacters(Converter(data[0]), Converter(data[1])); - data += 2; - } - - if (rem) - hasher.addCharacter(Converter(*data)); - + hasher.addCharactersAssumingAligned<T, Converter>(data, length); return hasher.hash(); } - template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data) + template<typename T, UChar Converter(T)> static unsigned computeHash(const T* data) { StringHasher hasher; - - while (true) { - UChar b0 = Converter(*data++); - if (!b0) - break; - UChar b1 = Converter(*data++); - if (!b1) { - hasher.addCharacter(b0); - break; - } - - hasher.addCharacters(b0, b1); - } - + hasher.addCharactersAssumingAligned<T, Converter>(data); return hasher.hash(); } - template<typename T> static inline unsigned computeHash(const T* data, unsigned length) + template<typename T> static unsigned computeHash(const T* data, unsigned length) { return computeHash<T, defaultConverter>(data, length); } - template<typename T> static inline unsigned computeHash(const T* data) + template<typename T> static unsigned computeHash(const T* data) { return computeHash<T, defaultConverter>(data); } - template<size_t length> static inline unsigned hashMemory(const void* data) + static unsigned hashMemory(const void* data, unsigned length) { - COMPILE_ASSERT(!(length % 4), length_must_be_a_multible_of_four); + // FIXME: Why does this function use the version of the hash that drops the top 8 bits? + // We want that for all string hashing so we can use those bits in StringImpl and hash + // strings consistently, but I don't see why we'd want that for general memory hashing. + ASSERT(!(length % 2)); return computeHashAndMaskTop8Bits<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar)); } - static inline unsigned hashMemory(const void* data, unsigned size) + template<size_t length> static unsigned hashMemory(const void* data) { - ASSERT(!(size % 2)); - return computeHashAndMaskTop8Bits<UChar>(static_cast<const UChar*>(data), size / sizeof(UChar)); + COMPILE_ASSERT(!(length % 2), length_must_be_a_multiple_of_two); + return hashMemory(data, length); } private: - static inline UChar defaultConverter(UChar ch) + static UChar defaultConverter(UChar character) { - return ch; + return character; } - static inline UChar defaultConverter(LChar ch) + static UChar defaultConverter(LChar character) { - return ch; - } - - inline void addCharactersToHash(UChar a, UChar b) - { - m_hash += a; - unsigned tmp = (b << 11) ^ m_hash; - m_hash = (m_hash << 16) ^ tmp; - m_hash += m_hash >> 11; + return character; } - inline unsigned avalancheBits() const + unsigned avalancheBits() const { unsigned result = m_hash; diff --git a/Source/WTF/wtf/StringPrintStream.cpp b/Source/WTF/wtf/StringPrintStream.cpp index 60e503043..09f447ad7 100644 --- a/Source/WTF/wtf/StringPrintStream.cpp +++ b/Source/WTF/wtf/StringPrintStream.cpp @@ -50,7 +50,7 @@ StringPrintStream::~StringPrintStream() void StringPrintStream::vprintf(const char* format, va_list argList) { - ASSERT(m_next < m_size); + ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size); ASSERT(!m_buffer[m_next]); va_list firstPassArgList; @@ -82,7 +82,7 @@ void StringPrintStream::vprintf(const char* format, va_list argList) m_next += numberOfBytesNotIncludingTerminatorThatWereWritten; - ASSERT(m_next < m_size); + ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size); ASSERT(!m_buffer[m_next]); } @@ -92,6 +92,18 @@ CString StringPrintStream::toCString() return CString(m_buffer, m_next); } +void StringPrintStream::reset() +{ + m_next = 0; + m_buffer[0] = 0; +} + +String StringPrintStream::toString() +{ + ASSERT(m_next == strlen(m_buffer)); + return String::fromUTF8(m_buffer, m_next); +} + void StringPrintStream::increaseSize(size_t newSize) { ASSERT(newSize > m_size); diff --git a/Source/WTF/wtf/StringPrintStream.h b/Source/WTF/wtf/StringPrintStream.h index 9290f0867..c6ed3ddc6 100644 --- a/Source/WTF/wtf/StringPrintStream.h +++ b/Source/WTF/wtf/StringPrintStream.h @@ -28,17 +28,20 @@ #include <wtf/PrintStream.h> #include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> namespace WTF { class StringPrintStream : public PrintStream { public: - StringPrintStream(); - ~StringPrintStream(); + WTF_EXPORT_PRIVATE StringPrintStream(); + WTF_EXPORT_PRIVATE ~StringPrintStream(); virtual void vprintf(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(2, 0); - CString toCString(); + WTF_EXPORT_PRIVATE CString toCString(); + WTF_EXPORT_PRIVATE String toString(); + WTF_EXPORT_PRIVATE void reset(); private: void increaseSize(size_t); @@ -58,10 +61,19 @@ CString toCString(const T& value) return stream.toCString(); } +template<typename T> +String toString(const T& value) +{ + StringPrintStream stream; + stream.print(value); + return stream.toString(); +} + } // namespace WTF using WTF::StringPrintStream; using WTF::toCString; +using WTF::toString; #endif // StringPrintStream_h diff --git a/Source/WTF/wtf/TCSystemAlloc.cpp b/Source/WTF/wtf/TCSystemAlloc.cpp index f547085e6..ae67918ed 100644 --- a/Source/WTF/wtf/TCSystemAlloc.cpp +++ b/Source/WTF/wtf/TCSystemAlloc.cpp @@ -35,8 +35,8 @@ #include "TCSystemAlloc.h" #include "Assertions.h" +#include "CheckedArithmetic.h" #include "TCSpinLock.h" -#include "UnusedParam.h" #include "VMTags.h" #include <algorithm> #include <stdint.h> @@ -166,7 +166,8 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { if (alignment > pagesize) { extra = alignment - pagesize; } - void* result = mmap(NULL, size + extra, + Checked<size_t> mapSize = Checked<size_t>(size) + extra + 2 * pagesize; + void* result = mmap(NULL, mapSize.unsafeGet(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, VM_TAG_FOR_TCMALLOC_MEMORY, 0); @@ -174,7 +175,9 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { mmap_failure = true; return NULL; } - + mmap(result, pagesize, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_TCMALLOC_MEMORY, 0); + mmap(static_cast<char*>(result) + (mapSize - pagesize).unsafeGet(), pagesize, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_TCMALLOC_MEMORY, 0); + result = static_cast<char*>(result) + pagesize; // Adjust the return memory so it is aligned uintptr_t ptr = reinterpret_cast<uintptr_t>(result); size_t adjust = 0; diff --git a/Source/WTF/wtf/ThreadFunctionInvocation.h b/Source/WTF/wtf/ThreadFunctionInvocation.h index 2d8599eb9..b9268e95b 100644 --- a/Source/WTF/wtf/ThreadFunctionInvocation.h +++ b/Source/WTF/wtf/ThreadFunctionInvocation.h @@ -34,6 +34,8 @@ namespace WTF { typedef void (*ThreadFunction)(void* argument); struct ThreadFunctionInvocation { + WTF_MAKE_FAST_ALLOCATED; +public: ThreadFunctionInvocation(ThreadFunction function, void* data) : function(function) , data(data) diff --git a/Source/WTF/wtf/ThreadIdentifierDataPthreads.cpp b/Source/WTF/wtf/ThreadIdentifierDataPthreads.cpp index 4ad20c8bc..bd62288f8 100644 --- a/Source/WTF/wtf/ThreadIdentifierDataPthreads.cpp +++ b/Source/WTF/wtf/ThreadIdentifierDataPthreads.cpp @@ -36,7 +36,7 @@ #include "Threading.h" -#if OS(ANDROID) || OS(HURD) +#if OS(HURD) // PTHREAD_KEYS_MAX is not defined in bionic nor in Hurd, so explicitly define it here. #define PTHREAD_KEYS_MAX 1024 #else diff --git a/Source/WTF/wtf/ThreadRestrictionVerifier.h b/Source/WTF/wtf/ThreadRestrictionVerifier.h index cff49d318..f7ada5094 100644 --- a/Source/WTF/wtf/ThreadRestrictionVerifier.h +++ b/Source/WTF/wtf/ThreadRestrictionVerifier.h @@ -47,7 +47,12 @@ namespace WTF { // The default mode is to verify that the object will only be used on a single thread. The // thread gets captured when setShared(true) is called. // The mode may be changed by calling useMutexMode (or turnOffVerification). -#if !USE(JSC) // This verifier is completely wrong for JavaScript implementations that use threads + +// FIXME: This verifier is switched off because it fires false positives for +// objects that are used on multiple threads. Instead of an opt-out verifier, +// we probably need an opt-in verifier that marks select objects as being +// tied to select threads. +#if 0 class ThreadRestrictionVerifier { public: ThreadRestrictionVerifier() @@ -169,7 +174,7 @@ private: dispatch_queue_t m_owningQueue; #endif }; -#else // !USE(JSC) => so the JSC case +#else class ThreadRestrictionVerifier { public: ThreadRestrictionVerifier() diff --git a/Source/WTF/wtf/ThreadSpecific.h b/Source/WTF/wtf/ThreadSpecific.h index 4ebece055..ffae09f68 100644 --- a/Source/WTF/wtf/ThreadSpecific.h +++ b/Source/WTF/wtf/ThreadSpecific.h @@ -170,10 +170,10 @@ WTF_EXPORT_PRIVATE DWORD* tlsKeys(); class PlatformThreadSpecificKey; typedef PlatformThreadSpecificKey* ThreadSpecificKey; -void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void *)); -void threadSpecificKeyDelete(ThreadSpecificKey); -void threadSpecificSet(ThreadSpecificKey, void*); -void* threadSpecificGet(ThreadSpecificKey); +WTF_EXPORT_PRIVATE void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void *)); +WTF_EXPORT_PRIVATE void threadSpecificKeyDelete(ThreadSpecificKey); +WTF_EXPORT_PRIVATE void threadSpecificSet(ThreadSpecificKey, void*); +WTF_EXPORT_PRIVATE void* threadSpecificGet(ThreadSpecificKey); template<typename T> inline ThreadSpecific<T>::ThreadSpecific() diff --git a/Source/WTF/wtf/ThreadSpecificWin.cpp b/Source/WTF/wtf/ThreadSpecificWin.cpp index d0f60ace1..9b70bbbca 100644 --- a/Source/WTF/wtf/ThreadSpecificWin.cpp +++ b/Source/WTF/wtf/ThreadSpecificWin.cpp @@ -22,6 +22,8 @@ #include "config.h" #include "ThreadSpecific.h" +#if OS(WINDOWS) + #include "StdLibExtras.h" #include "ThreadingPrimitives.h" #include <wtf/DoublyLinkedList.h> @@ -32,13 +34,13 @@ namespace WTF { static DoublyLinkedList<PlatformThreadSpecificKey>& destructorsList() { - DEFINE_STATIC_LOCAL(DoublyLinkedList<PlatformThreadSpecificKey>, staticList, ()); + static DoublyLinkedList<PlatformThreadSpecificKey> staticList; return staticList; } static Mutex& destructorsMutex() { - DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); + static Mutex staticMutex; return staticMutex; } @@ -89,7 +91,9 @@ DWORD* tlsKeys() void threadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void *)) { - *key = new PlatformThreadSpecificKey(destructor); + // Use the original malloc() instead of fastMalloc() to use this function in FastMalloc code. + *key = static_cast<PlatformThreadSpecificKey*>(::malloc(sizeof(PlatformThreadSpecificKey))); + new (*key) PlatformThreadSpecificKey(destructor); MutexLocker locker(destructorsMutex()); destructorsList().push(*key); @@ -99,7 +103,8 @@ void threadSpecificKeyDelete(ThreadSpecificKey key) { MutexLocker locker(destructorsMutex()); destructorsList().remove(key); - delete key; + key->~PlatformThreadSpecificKey(); + ::free(key); } void threadSpecificSet(ThreadSpecificKey key, void* data) @@ -133,3 +138,5 @@ void ThreadSpecificThreadExit() } // namespace WTF #endif // !USE(PTHREADS) + +#endif // OS(WINDOWS) diff --git a/Source/WTF/wtf/Threading.cpp b/Source/WTF/wtf/Threading.cpp index 8d658e934..c3ff58315 100644 --- a/Source/WTF/wtf/Threading.cpp +++ b/Source/WTF/wtf/Threading.cpp @@ -73,8 +73,8 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* { // Visual Studio has a 31-character limit on thread names. Longer names will // be truncated silently, but we'd like callers to know about the limit. -#if !LOG_DISABLED - if (strlen(name) > 31) +#if !LOG_DISABLED && PLATFORM(WIN) + if (name && strlen(name) > 31) LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name); #endif diff --git a/Source/WTF/wtf/ThreadingNone.cpp b/Source/WTF/wtf/ThreadingNone.cpp deleted file mode 100644 index e69de29bb..000000000 --- a/Source/WTF/wtf/ThreadingNone.cpp +++ /dev/null diff --git a/Source/WTF/wtf/ThreadingPthreads.cpp b/Source/WTF/wtf/ThreadingPthreads.cpp index 75fa19e78..03dbeec7e 100644 --- a/Source/WTF/wtf/ThreadingPthreads.cpp +++ b/Source/WTF/wtf/ThreadingPthreads.cpp @@ -44,7 +44,6 @@ #include "ThreadFunctionInvocation.h" #include "ThreadIdentifierDataPthreads.h" #include "ThreadSpecific.h" -#include "UnusedParam.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> #include <wtf/WTFThreadData.h> @@ -56,7 +55,7 @@ #include <sys/time.h> #endif -#if OS(MAC_OS_X) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 +#if OS(MAC_OS_X) #include <objc/objc-auto.h> #endif @@ -223,7 +222,7 @@ void initializeCurrentThreadInternal(const char* threadName) UNUSED_PARAM(threadName); #endif -#if OS(MAC_OS_X) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 +#if OS(MAC_OS_X) // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C // garbage collector in case API implementations use garbage-collected memory. objc_registerThreadWithCollector(); diff --git a/Source/WTF/wtf/ThreadingWin.cpp b/Source/WTF/wtf/ThreadingWin.cpp index d33973daf..49ecc1ae7 100644 --- a/Source/WTF/wtf/ThreadingWin.cpp +++ b/Source/WTF/wtf/ThreadingWin.cpp @@ -85,6 +85,9 @@ #include "config.h" #include "Threading.h" + +#if OS(WINDOWS) + #include "DateMath.h" #include "dtoa.h" #include "dtoa/cached-powers.h" @@ -515,3 +518,5 @@ DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) } } // namespace WTF + +#endif // OS(WINDOWS) diff --git a/Source/WTF/wtf/url/api/URLString.cpp b/Source/WTF/wtf/TriState.h index 9147fe399..69d585d1b 100644 --- a/Source/WTF/wtf/url/api/URLString.cpp +++ b/Source/WTF/wtf/TriState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,23 +20,30 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "URLString.h" - -#if USE(WTFURL) +#ifndef TriState_h +#define TriState_h namespace WTF { -#ifndef NDEBUG -void URLString::print() const +enum TriState { + FalseTriState, + TrueTriState, + MixedTriState +}; + +inline TriState triState(bool boolean) { - m_string.show(); + return static_cast<TriState>(boolean); } -#endif // ndef NDEBUG } -#endif // USE(WTFURL) +using WTF::TriState; +using WTF::FalseTriState; +using WTF::TrueTriState; +using WTF::MixedTriState; + +#endif // TriState_h diff --git a/Source/WTF/wtf/TypedArrayBase.h b/Source/WTF/wtf/TypedArrayBase.h index 6d2a0f2b8..ade824fa8 100644 --- a/Source/WTF/wtf/TypedArrayBase.h +++ b/Source/WTF/wtf/TypedArrayBase.h @@ -69,7 +69,7 @@ class TypedArrayBase : public ArrayBufferView { // is responsible for doing so and returning undefined as necessary. T item(unsigned index) const { - ASSERT(index < TypedArrayBase<T>::m_length); + ASSERT_WITH_SECURITY_IMPLICATION(index < TypedArrayBase<T>::m_length); return TypedArrayBase<T>::data()[index]; } diff --git a/Source/WTF/wtf/Uint16Array.h b/Source/WTF/wtf/Uint16Array.h index 144469386..ecf5f9c99 100644 --- a/Source/WTF/wtf/Uint16Array.h +++ b/Source/WTF/wtf/Uint16Array.h @@ -43,9 +43,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Uint16Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned short>* array, unsigned offset) { return TypedArrayBase<unsigned short>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned short>::set(index, value); } + using TypedArrayBase<unsigned short>::set; + using IntegralTypedArrayBase<unsigned short>::set; inline PassRefPtr<Uint16Array> subarray(int start) const; inline PassRefPtr<Uint16Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/Uint32Array.h b/Source/WTF/wtf/Uint32Array.h index 1e5b02823..1badf6bfc 100644 --- a/Source/WTF/wtf/Uint32Array.h +++ b/Source/WTF/wtf/Uint32Array.h @@ -43,9 +43,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Uint32Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned int>* array, unsigned offset) { return TypedArrayBase<unsigned int>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned int>::set(index, value); } + using TypedArrayBase<unsigned>::set; + using IntegralTypedArrayBase<unsigned>::set; inline PassRefPtr<Uint32Array> subarray(int start) const; inline PassRefPtr<Uint32Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/Uint8Array.h b/Source/WTF/wtf/Uint8Array.h index a23d1eb50..8caf05476 100644 --- a/Source/WTF/wtf/Uint8Array.h +++ b/Source/WTF/wtf/Uint8Array.h @@ -43,9 +43,8 @@ public: // not return these results directly to JavaScript without filling first. static inline PassRefPtr<Uint8Array> createUninitialized(unsigned length); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned char>* array, unsigned offset) { return TypedArrayBase<unsigned char>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned char>::set(index, value); } + using TypedArrayBase<unsigned char>::set; + using IntegralTypedArrayBase<unsigned char>::set; inline PassRefPtr<Uint8Array> subarray(int start) const; inline PassRefPtr<Uint8Array> subarray(int start, int end) const; diff --git a/Source/WTF/wtf/Uint8ClampedArray.h b/Source/WTF/wtf/Uint8ClampedArray.h index f3d92ac24..75cc2d82b 100644 --- a/Source/WTF/wtf/Uint8ClampedArray.h +++ b/Source/WTF/wtf/Uint8ClampedArray.h @@ -50,8 +50,7 @@ public: // zero the allocated memory. inline void zeroFill(); - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned char>* array, unsigned offset) { return TypedArrayBase<unsigned char>::set(array, offset); } + using TypedArrayBase<unsigned char>::set; inline void set(unsigned index, double value); inline PassRefPtr<Uint8ClampedArray> subarray(int start) const; @@ -99,7 +98,7 @@ void Uint8ClampedArray::set(unsigned index, double value) { if (index >= m_length) return; - if (isnan(value) || value < 0) + if (std::isnan(value) || value < 0) value = 0; else if (value > 255) value = 255; diff --git a/Source/WTF/wtf/StringExtras.cpp b/Source/WTF/wtf/UniStdExtras.h index 1b96417c8..14acff1e7 100644 --- a/Source/WTF/wtf/StringExtras.cpp +++ b/Source/WTF/wtf/UniStdExtras.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Company 100, Inc. All rights reserved. + * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,53 +10,45 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#ifndef UniStdExtras_h +#define UniStdExtras_h -#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 +#include <errno.h> +#include <unistd.h> -#include "StringExtras.h" +namespace WTF { -#include "ASCIICType.h" - -int strcasecmp(const char* s1, const char* s2) +inline int closeWithRetry(int fileDescriptor) { - while (toASCIIUpper(*s1) == toASCIIUpper(*s2)) { - if (*s1 == '\0') - return 0; - s1++; - s2++; - } - - return toASCIIUpper(*s1) - toASCIIUpper(*s2); + int ret; +#if OS(LINUX) + // Workaround for the Linux behavior of closing the descriptor + // unconditionally, even if the close() call is interrupted. + // See https://bugs.webkit.org/show_bug.cgi?id=117266 for more + // details. + if ((ret = close(fileDescriptor)) == -1 && errno == EINTR) + return 0; +#else + while ((ret = close(fileDescriptor)) == -1 && errno == EINTR) { } +#endif + return ret; } -int strncasecmp(const char* s1, const char* s2, size_t len) -{ - while (len > 0 && toASCIIUpper(*s1) == toASCIIUpper(*s2)) { - if (*s1 == '\0') - return 0; - s1++; - s2++; - len--; - } +} // namespace WTF - if (!len) - return 0; - - return toASCIIUpper(*s1) - toASCIIUpper(*s2); -} +using WTF::closeWithRetry; -#endif +#endif // UniStdExtras_h diff --git a/Source/WTF/wtf/UnusedParam.h b/Source/WTF/wtf/UnusedParam.h deleted file mode 100644 index 31d70e736..000000000 --- a/Source/WTF/wtf/UnusedParam.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_UnusedParam_h -#define WTF_UnusedParam_h - -#include <wtf/Platform.h> - -#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) -template<typename T> -inline void unusedParam(T& x) { (void)x; } -#define UNUSED_PARAM(variable) unusedParam(variable) -#else -#define UNUSED_PARAM(variable) (void)variable -#endif - -/* This is to keep the compiler from complaining when for local labels are - declared but not referenced. For example, this can happen with code that - works with auto-generated code. -*/ -#if COMPILER(MSVC) -#define UNUSED_LABEL(label) if (false) goto label -#else -#define UNUSED_LABEL(label) UNUSED_PARAM(&& label) -#endif - -#endif /* WTF_UnusedParam_h */ diff --git a/Source/WTF/wtf/Vector.h b/Source/WTF/wtf/Vector.h index d2dedefea..66d46a6cc 100644 --- a/Source/WTF/wtf/Vector.h +++ b/Source/WTF/wtf/Vector.h @@ -22,11 +22,11 @@ #define WTF_Vector_h #include <wtf/Alignment.h> +#include <wtf/CheckedArithmetic.h> #include <wtf/FastAllocBase.h> #include <wtf/Noncopyable.h> #include <wtf/NotFound.h> #include <wtf/StdLibExtras.h> -#include <wtf/UnusedParam.h> #include <wtf/ValueCheck.h> #include <wtf/VectorTraits.h> #include <limits> @@ -252,21 +252,23 @@ namespace WTF { void allocateBuffer(size_t newCapacity) { ASSERT(newCapacity); - m_capacity = newCapacity; - if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) + if (newCapacity > std::numeric_limits<unsigned>::max() / sizeof(T)) CRASH(); - m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T))); + size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T)); + m_capacity = sizeToAllocate / sizeof(T); + m_buffer = static_cast<T*>(fastMalloc(sizeToAllocate)); } bool tryAllocateBuffer(size_t newCapacity) { ASSERT(newCapacity); - if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) + if (newCapacity > std::numeric_limits<unsigned>::max() / sizeof(T)) return false; + size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T)); T* newBuffer; - if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) { - m_capacity = newCapacity; + if (tryFastMalloc(sizeToAllocate).getValue(newBuffer)) { + m_capacity = sizeToAllocate / sizeof(T); m_buffer = newBuffer; return true; } @@ -281,10 +283,11 @@ namespace WTF { void reallocateBuffer(size_t newCapacity) { ASSERT(shouldReallocateBuffer(newCapacity)); - m_capacity = newCapacity; if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) CRASH(); - m_buffer = static_cast<T*>(fastRealloc(m_buffer, newCapacity * sizeof(T))); + size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T)); + m_capacity = sizeToAllocate / sizeof(T); + m_buffer = static_cast<T*>(fastRealloc(m_buffer, sizeToAllocate)); } void deallocateBuffer(T* bufferToDeallocate) @@ -331,7 +334,7 @@ namespace WTF { } T* m_buffer; - size_t m_capacity; + unsigned m_capacity; }; template<typename T, size_t inlineCapacity> @@ -435,7 +438,7 @@ namespace WTF { bool shouldReallocateBuffer(size_t newCapacity) const { // We cannot reallocate the inline buffer. - return Base::shouldReallocateBuffer(newCapacity) && std::min(m_capacity, newCapacity) > inlineCapacity; + return Base::shouldReallocateBuffer(newCapacity) && std::min(static_cast<size_t>(m_capacity), newCapacity) > inlineCapacity; } void reallocateBuffer(size_t newCapacity) @@ -493,12 +496,19 @@ namespace WTF { AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; }; + + struct UnsafeVectorOverflow { + static NO_RETURN_DUE_TO_ASSERT void overflowed() + { + ASSERT_NOT_REACHED(); + } + }; - template<typename T, size_t inlineCapacity = 0> - class Vector { + template<typename T, size_t inlineCapacity = 0, typename OverflowHandler = CrashOnOverflow> + class Vector : private VectorBuffer<T, inlineCapacity> { WTF_MAKE_FAST_ALLOCATED; private: - typedef VectorBuffer<T, inlineCapacity> Buffer; + typedef VectorBuffer<T, inlineCapacity> Base; typedef VectorTypeOperations<T> TypeOperations; public: @@ -509,14 +519,14 @@ namespace WTF { typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - Vector() + Vector() : m_size(0) { } - explicit Vector(size_t size) - : m_size(size) - , m_buffer(size) + explicit Vector(size_t size) + : Base(size) + , m_size(size) { if (begin()) TypeOperations::initialize(begin(), end()); @@ -529,12 +539,12 @@ namespace WTF { } Vector(const Vector&); - template<size_t otherCapacity> - Vector(const Vector<T, otherCapacity>&); + template<size_t otherCapacity, typename otherOverflowBehaviour> + Vector(const Vector<T, otherCapacity, otherOverflowBehaviour>&); Vector& operator=(const Vector&); - template<size_t otherCapacity> - Vector& operator=(const Vector<T, otherCapacity>&); + template<size_t otherCapacity, typename otherOverflowBehaviour> + Vector& operator=(const Vector<T, otherCapacity, otherOverflowBehaviour>&); #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) Vector(Vector&&); @@ -542,26 +552,39 @@ namespace WTF { #endif size_t size() const { return m_size; } - size_t capacity() const { return m_buffer.capacity(); } + size_t capacity() const { return Base::capacity(); } bool isEmpty() const { return !size(); } - T& at(size_t i) - { - ASSERT(i < size()); - return m_buffer.buffer()[i]; + T& at(size_t i) + { + if (UNLIKELY(i >= size())) + OverflowHandler::overflowed(); + return Base::buffer()[i]; } const T& at(size_t i) const { - ASSERT(i < size()); - return m_buffer.buffer()[i]; + if (UNLIKELY(i >= size())) + OverflowHandler::overflowed(); + return Base::buffer()[i]; + } + T& at(Checked<size_t> i) + { + RELEASE_ASSERT(i < size()); + return Base::buffer()[i]; + } + const T& at(Checked<size_t> i) const + { + RELEASE_ASSERT(i < size()); + return Base::buffer()[i]; } T& operator[](size_t i) { return at(i); } const T& operator[](size_t i) const { return at(i); } + T& operator[](Checked<size_t> i) { return at(i); } + const T& operator[](Checked<size_t> i) const { return at(i); } - T* data() { return m_buffer.buffer(); } - const T* data() const { return m_buffer.buffer(); } - T** dataSlot() { return m_buffer.bufferSlot(); } + T* data() { return Base::buffer(); } + const T* data() const { return Base::buffer(); } iterator begin() { return data(); } iterator end() { return begin() + m_size; } @@ -585,6 +608,7 @@ namespace WTF { void shrink(size_t size); void grow(size_t size); void resize(size_t size); + void resizeToFit(size_t size); void reserveCapacity(size_t newCapacity); bool tryReserveCapacity(size_t newCapacity); void reserveInitialCapacity(size_t initialCapacity); @@ -596,7 +620,6 @@ namespace WTF { template<typename U> void append(const U*, size_t); template<typename U> void append(const U&); template<typename U> void uncheckedAppend(const U& val); - template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&); template<typename U, size_t otherCapacity> void appendVector(const Vector<U, otherCapacity>&); template<typename U> bool tryAppend(const U*, size_t); @@ -604,22 +627,19 @@ namespace WTF { template<typename U> void insert(size_t position, const U&); template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&); - template<typename U> void prepend(const U*, size_t); - template<typename U> void prepend(const U&); - template<typename U, size_t c> void prepend(const Vector<U, c>&); - void remove(size_t position); void remove(size_t position, size_t length); void removeLast() { - ASSERT(!isEmpty()); + if (UNLIKELY(isEmpty())) + OverflowHandler::overflowed(); shrink(size() - 1); } Vector(size_t size, const T& val) - : m_size(size) - , m_buffer(size) + : Base(size) + , m_size(size) { if (begin()) TypeOperations::uninitializedFill(begin(), end(), val); @@ -632,10 +652,10 @@ namespace WTF { T* releaseBuffer(); - void swap(Vector<T, inlineCapacity>& other) + void swap(Vector<T, inlineCapacity, OverflowHandler>& other) { std::swap(m_size, other.m_size); - m_buffer.swap(other.m_buffer); + Base::swap(other); } void reverse(); @@ -650,31 +670,41 @@ namespace WTF { template<typename U> U* expandCapacity(size_t newMinCapacity, U*); template<typename U> void appendSlowCase(const U&); - size_t m_size; - Buffer m_buffer; + unsigned m_size; + + using Base::buffer; + using Base::capacity; + using Base::swap; + using Base::allocateBuffer; + using Base::deallocateBuffer; + using Base::tryAllocateBuffer; + using Base::shouldReallocateBuffer; + using Base::reallocateBuffer; + using Base::restoreInlineBufferIfNeeded; + using Base::releaseBuffer; }; - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>::Vector(const Vector& other) - : m_size(other.size()) - , m_buffer(other.capacity()) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + Vector<T, inlineCapacity, OverflowHandler>::Vector(const Vector& other) + : Base(other.capacity()) + , m_size(other.size()) { if (begin()) TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); } - template<typename T, size_t inlineCapacity> - template<size_t otherCapacity> - Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other) - : m_size(other.size()) - , m_buffer(other.capacity()) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + template<size_t otherCapacity, typename otherOverflowBehaviour> + Vector<T, inlineCapacity, OverflowHandler>::Vector(const Vector<T, otherCapacity, otherOverflowBehaviour>& other) + : Base(other.capacity()) + , m_size(other.size()) { if (begin()) TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); } - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(const Vector<T, inlineCapacity, OverflowHandler>& other) { if (&other == this) return *this; @@ -703,9 +733,9 @@ namespace WTF { inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } - template<typename T, size_t inlineCapacity> - template<size_t otherCapacity> - Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + template<size_t otherCapacity, typename otherOverflowBehaviour> + Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(const Vector<T, otherCapacity, otherOverflowBehaviour>& other) { // If the inline capacities match, we should call the more specific // template. If the inline capacities don't match, the two objects @@ -735,8 +765,8 @@ namespace WTF { } #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>::Vector(Vector<T, inlineCapacity>&& other) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + Vector<T, inlineCapacity, OverflowHandler>::Vector(Vector<T, inlineCapacity, OverflowHandler>&& other) : m_size(0) { // It's a little weird to implement a move constructor using swap but this way we @@ -744,24 +774,24 @@ namespace WTF { swap(other); } - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(Vector<T, inlineCapacity>&& other) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(Vector<T, inlineCapacity, OverflowHandler>&& other) { swap(other); return *this; } #endif - template<typename T, size_t inlineCapacity> + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> - bool Vector<T, inlineCapacity>::contains(const U& value) const + bool Vector<T, inlineCapacity, OverflowHandler>::contains(const U& value) const { return find(value) != notFound; } - template<typename T, size_t inlineCapacity> + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> - size_t Vector<T, inlineCapacity>::find(const U& value) const + size_t Vector<T, inlineCapacity, OverflowHandler>::find(const U& value) const { for (size_t i = 0; i < size(); ++i) { if (at(i) == value) @@ -770,9 +800,9 @@ namespace WTF { return notFound; } - template<typename T, size_t inlineCapacity> + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> - size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const + size_t Vector<T, inlineCapacity, OverflowHandler>::reverseFind(const U& value) const { for (size_t i = 1; i <= size(); ++i) { const size_t index = size() - i; @@ -782,8 +812,8 @@ namespace WTF { return notFound; } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::fill(const T& val, size_t newSize) { if (size() > newSize) shrink(newSize); @@ -799,22 +829,22 @@ namespace WTF { m_size = newSize; } - template<typename T, size_t inlineCapacity> + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename Iterator> - void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end) + void Vector<T, inlineCapacity, OverflowHandler>::appendRange(Iterator start, Iterator end) { for (Iterator it = start; it != end; ++it) append(*it); } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity) { reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); } - template<typename T, size_t inlineCapacity> - const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + const T* Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity, const T* ptr) { if (ptr < begin() || ptr >= end()) { expandCapacity(newMinCapacity); @@ -825,14 +855,14 @@ namespace WTF { return begin() + index; } - template<typename T, size_t inlineCapacity> - bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + bool Vector<T, inlineCapacity, OverflowHandler>::tryExpandCapacity(size_t newMinCapacity) { return tryReserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); } - template<typename T, size_t inlineCapacity> - const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + const T* Vector<T, inlineCapacity, OverflowHandler>::tryExpandCapacity(size_t newMinCapacity, const T* ptr) { if (ptr < begin() || ptr >= end()) { if (!tryExpandCapacity(newMinCapacity)) @@ -845,15 +875,15 @@ namespace WTF { return begin() + index; } - template<typename T, size_t inlineCapacity> template<typename U> - inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + inline U* Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity, U* ptr) { expandCapacity(newMinCapacity); return ptr; } - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::resize(size_t size) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::resize(size_t size) { if (size <= m_size) TypeOperations::destruct(begin() + size, end()); @@ -867,16 +897,23 @@ namespace WTF { m_size = size; } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::shrink(size_t size) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::resizeToFit(size_t size) + { + reserveCapacity(size); + resize(size); + } + + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::shrink(size_t size) { ASSERT(size <= m_size); TypeOperations::destruct(begin() + size, end()); m_size = size; } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::grow(size_t size) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::grow(size_t size) { ASSERT(size >= m_size); if (size > capacity()) @@ -886,45 +923,45 @@ namespace WTF { m_size = size; } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::reserveCapacity(size_t newCapacity) { if (newCapacity <= capacity()) return; T* oldBuffer = begin(); T* oldEnd = end(); - m_buffer.allocateBuffer(newCapacity); + Base::allocateBuffer(newCapacity); if (begin()) TypeOperations::move(oldBuffer, oldEnd, begin()); - m_buffer.deallocateBuffer(oldBuffer); + Base::deallocateBuffer(oldBuffer); } - template<typename T, size_t inlineCapacity> - bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + bool Vector<T, inlineCapacity, OverflowHandler>::tryReserveCapacity(size_t newCapacity) { if (newCapacity <= capacity()) return true; T* oldBuffer = begin(); T* oldEnd = end(); - if (!m_buffer.tryAllocateBuffer(newCapacity)) + if (!Base::tryAllocateBuffer(newCapacity)) return false; ASSERT(begin()); TypeOperations::move(oldBuffer, oldEnd, begin()); - m_buffer.deallocateBuffer(oldBuffer); + Base::deallocateBuffer(oldBuffer); return true; } - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::reserveInitialCapacity(size_t initialCapacity) { ASSERT(!m_size); ASSERT(capacity() == inlineCapacity); if (initialCapacity > inlineCapacity) - m_buffer.allocateBuffer(initialCapacity); + Base::allocateBuffer(initialCapacity); } - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void Vector<T, inlineCapacity, OverflowHandler>::shrinkCapacity(size_t newCapacity) { if (newCapacity >= capacity()) return; @@ -934,27 +971,27 @@ namespace WTF { T* oldBuffer = begin(); if (newCapacity > 0) { - if (m_buffer.shouldReallocateBuffer(newCapacity)) { - m_buffer.reallocateBuffer(newCapacity); + if (Base::shouldReallocateBuffer(newCapacity)) { + Base::reallocateBuffer(newCapacity); return; } T* oldEnd = end(); - m_buffer.allocateBuffer(newCapacity); + Base::allocateBuffer(newCapacity); if (begin() != oldBuffer) TypeOperations::move(oldBuffer, oldEnd, begin()); } - m_buffer.deallocateBuffer(oldBuffer); - m_buffer.restoreInlineBufferIfNeeded(); + Base::deallocateBuffer(oldBuffer); + Base::restoreInlineBufferIfNeeded(); } // Templatizing these is better than just letting the conversion happen implicitly, // because for instance it allows a PassRefPtr to be appended to a RefPtr vector // without refcount thrash. - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + void Vector<T, inlineCapacity, OverflowHandler>::append(const U* data, size_t dataSize) { size_t newSize = m_size + dataSize; if (newSize > capacity()) { @@ -970,8 +1007,8 @@ namespace WTF { m_size = newSize; } - template<typename T, size_t inlineCapacity> template<typename U> - bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + bool Vector<T, inlineCapacity, OverflowHandler>::tryAppend(const U* data, size_t dataSize) { size_t newSize = m_size + dataSize; if (newSize > capacity()) { @@ -989,8 +1026,8 @@ namespace WTF { return true; } - template<typename T, size_t inlineCapacity> template<typename U> - ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + ALWAYS_INLINE void Vector<T, inlineCapacity, OverflowHandler>::append(const U& val) { if (size() != capacity()) { new (NotNull, end()) T(val); @@ -1001,8 +1038,8 @@ namespace WTF { appendSlowCase(val); } - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::appendSlowCase(const U& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + void Vector<T, inlineCapacity, OverflowHandler>::appendSlowCase(const U& val) { ASSERT(size() == capacity()); @@ -1018,8 +1055,8 @@ namespace WTF { // This version of append saves a branch in the case where you know that the // vector's capacity is large enough for the append to succeed. - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + inline void Vector<T, inlineCapacity, OverflowHandler>::uncheckedAppend(const U& val) { ASSERT(size() < capacity()); const U* ptr = &val; @@ -1027,25 +1064,16 @@ namespace WTF { ++m_size; } - // This method should not be called append, a better name would be appendElements. - // It could also be eliminated entirely, and call sites could just use - // appendRange(val.begin(), val.end()). - template<typename T, size_t inlineCapacity> template<size_t otherCapacity> - inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val) - { - append(val.begin(), val.size()); - } - - template<typename T, size_t inlineCapacity> template<typename U, size_t otherCapacity> - inline void Vector<T, inlineCapacity>::appendVector(const Vector<U, otherCapacity>& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U, size_t otherCapacity> + inline void Vector<T, inlineCapacity, OverflowHandler>::appendVector(const Vector<U, otherCapacity>& val) { append(val.begin(), val.size()); } - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const U* data, size_t dataSize) { - ASSERT(position <= size()); + ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); size_t newSize = m_size + dataSize; if (newSize > capacity()) { data = expandCapacity(newSize, data); @@ -1061,10 +1089,10 @@ namespace WTF { m_size = newSize; } - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U> + inline void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const U& val) { - ASSERT(position <= size()); + ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); const U* data = &val; if (size() == capacity()) { data = expandCapacity(size() + 1, data); @@ -1077,45 +1105,27 @@ namespace WTF { ++m_size; } - template<typename T, size_t inlineCapacity> template<typename U, size_t c> - inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val) + template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U, size_t c> + inline void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const Vector<U, c>& val) { insert(position, val.begin(), val.size()); } - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize) - { - insert(0, data, dataSize); - } - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::prepend(const U& val) - { - insert(0, val); - } - - template<typename T, size_t inlineCapacity> template<typename U, size_t c> - inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val) - { - insert(0, val.begin(), val.size()); - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::remove(size_t position) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::remove(size_t position) { - ASSERT(position < size()); + ASSERT_WITH_SECURITY_IMPLICATION(position < size()); T* spot = begin() + position; spot->~T(); TypeOperations::moveOverlapping(spot + 1, end(), spot); --m_size; } - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::remove(size_t position, size_t length) { - ASSERT(position <= size()); - ASSERT(position + length <= size()); + ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); + ASSERT_WITH_SECURITY_IMPLICATION(position + length <= size()); T* beginSpot = begin() + position; T* endSpot = beginSpot + length; TypeOperations::destruct(beginSpot, endSpot); @@ -1123,17 +1133,17 @@ namespace WTF { m_size -= length; } - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::reverse() + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::reverse() { for (size_t i = 0; i < m_size / 2; ++i) std::swap(at(i), at(m_size - 1 - i)); } - template<typename T, size_t inlineCapacity> - inline T* Vector<T, inlineCapacity>::releaseBuffer() + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline T* Vector<T, inlineCapacity, OverflowHandler>::releaseBuffer() { - T* buffer = m_buffer.releaseBuffer(); + T* buffer = Base::releaseBuffer(); if (inlineCapacity && !buffer && m_size) { // If the vector had some data, but no buffer to release, // that means it was using the inline buffer. In that case, @@ -1146,8 +1156,8 @@ namespace WTF { return buffer; } - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::checkConsistency() + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void Vector<T, inlineCapacity, OverflowHandler>::checkConsistency() { #if !ASSERT_DISABLED for (size_t i = 0; i < size(); ++i) @@ -1155,23 +1165,23 @@ namespace WTF { #endif } - template<typename T, size_t inlineCapacity> - void deleteAllValues(const Vector<T, inlineCapacity>& collection) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + void deleteAllValues(const Vector<T, inlineCapacity, OverflowHandler>& collection) { - typedef typename Vector<T, inlineCapacity>::const_iterator iterator; + typedef typename Vector<T, inlineCapacity, OverflowHandler>::const_iterator iterator; iterator end = collection.end(); for (iterator it = collection.begin(); it != end; ++it) delete *it; } - template<typename T, size_t inlineCapacity> - inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline void swap(Vector<T, inlineCapacity, OverflowHandler>& a, Vector<T, inlineCapacity, OverflowHandler>& b) { a.swap(b); } - template<typename T, size_t inlineCapacity> - bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + bool operator==(const Vector<T, inlineCapacity, OverflowHandler>& a, const Vector<T, inlineCapacity, OverflowHandler>& b) { if (a.size() != b.size()) return false; @@ -1179,8 +1189,8 @@ namespace WTF { return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); } - template<typename T, size_t inlineCapacity> - inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) + template<typename T, size_t inlineCapacity, typename OverflowHandler> + inline bool operator!=(const Vector<T, inlineCapacity, OverflowHandler>& a, const Vector<T, inlineCapacity, OverflowHandler>& b) { return !(a == b); } @@ -1198,5 +1208,6 @@ namespace WTF { } // namespace WTF using WTF::Vector; +using WTF::UnsafeVectorOverflow; #endif // WTF_Vector_h diff --git a/Source/WTF/wtf/VectorTraits.h b/Source/WTF/wtf/VectorTraits.h index 678225034..4b0834427 100644 --- a/Source/WTF/wtf/VectorTraits.h +++ b/Source/WTF/wtf/VectorTraits.h @@ -21,6 +21,7 @@ #ifndef WTF_VectorTraits_h #define WTF_VectorTraits_h +#include <wtf/OwnArrayPtr.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> #include <wtf/TypeTraits.h> @@ -78,6 +79,9 @@ namespace WTF { template<typename P> struct VectorTraits<OwnPtr<P> > : SimpleClassVectorTraits { }; + template<typename P> + struct VectorTraits<OwnArrayPtr<P> > : SimpleClassVectorTraits { }; + template<> struct VectorTraits<AtomicString> : SimpleClassVectorTraits { }; diff --git a/Source/WTF/wtf/WTFThreadData.cpp b/Source/WTF/wtf/WTFThreadData.cpp index 7d9074844..5c20181b2 100644 --- a/Source/WTF/wtf/WTFThreadData.cpp +++ b/Source/WTF/wtf/WTFThreadData.cpp @@ -27,36 +27,35 @@ #include "config.h" #include "WTFThreadData.h" +#include <wtf/text/AtomicStringTable.h> + namespace WTF { ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; WTFThreadData::WTFThreadData() - : m_atomicStringTable(0) + : m_apiData(0) + , m_atomicStringTable(0) , m_atomicStringTableDestructor(0) -#if USE(JSC) , m_defaultIdentifierTable(new JSC::IdentifierTable()) , m_currentIdentifierTable(m_defaultIdentifierTable) , m_stackBounds(StackBounds::currentThreadStackBounds()) #if ENABLE(STACK_STATS) , m_stackStats() #endif -#endif // USE(JSC) { + AtomicStringTable::create(*this); } WTFThreadData::~WTFThreadData() { if (m_atomicStringTableDestructor) m_atomicStringTableDestructor(m_atomicStringTable); -#if USE(JSC) delete m_defaultIdentifierTable; -#endif } } // namespace WTF -#if USE(JSC) namespace JSC { IdentifierTable::~IdentifierTable() @@ -74,5 +73,3 @@ HashSet<StringImpl*>::AddResult IdentifierTable::add(StringImpl* value) } } // namespace JSC -#endif - diff --git a/Source/WTF/wtf/WTFThreadData.h b/Source/WTF/wtf/WTFThreadData.h index a48ad62d3..fa157e978 100644 --- a/Source/WTF/wtf/WTFThreadData.h +++ b/Source/WTF/wtf/WTFThreadData.h @@ -36,18 +36,15 @@ #include <wtf/ThreadSpecific.h> #include <wtf/Threading.h> -#if USE(JSC) // FIXME: This is a temporary layering violation while we move more string code to WTF. namespace JSC { -typedef HashMap<const char*, RefPtr<StringImpl>, PtrHash<const char*> > LiteralIdentifierTable; - class IdentifierTable { WTF_MAKE_FAST_ALLOCATED; public: - ~IdentifierTable(); + WTF_EXPORT_PRIVATE ~IdentifierTable(); - HashSet<StringImpl*>::AddResult add(StringImpl* value); + WTF_EXPORT_PRIVATE HashSet<StringImpl*>::AddResult add(StringImpl* value); template<typename U, typename V> HashSet<StringImpl*>::AddResult add(U value); @@ -60,15 +57,11 @@ public: return true; } - LiteralIdentifierTable& literalTable() { return m_literalTable; } - private: HashSet<StringImpl*> m_table; - LiteralIdentifierTable m_literalTable; }; } -#endif namespace WTF { @@ -87,7 +80,6 @@ public: return m_atomicStringTable; } -#if USE(JSC) JSC::IdentifierTable* currentIdentifierTable() { return m_currentIdentifierTable; @@ -121,20 +113,19 @@ public: return m_stackStats; } #endif -#endif // USE(JSC) + + void* m_apiData; private: AtomicStringTable* m_atomicStringTable; AtomicStringTableDestructor m_atomicStringTableDestructor; -#if USE(JSC) JSC::IdentifierTable* m_defaultIdentifierTable; JSC::IdentifierTable* m_currentIdentifierTable; StackBounds m_stackBounds; #if ENABLE(STACK_STATS) StackStats::PerThreadStats m_stackStats; #endif -#endif // USE(JSC) static WTF_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData; friend WTFThreadData& wtfThreadData(); diff --git a/Source/WTF/wtf/WeakPtr.h b/Source/WTF/wtf/WeakPtr.h new file mode 100644 index 000000000..aa15318a4 --- /dev/null +++ b/Source/WTF/wtf/WeakPtr.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2013 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 WTF_WeakPtr_h +#define WTF_WeakPtr_h + +#include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/ThreadSafeRefCounted.h> +#include <wtf/Threading.h> + +namespace WTF { + +template<typename T> +class WeakReference : public ThreadSafeRefCounted<WeakReference<T> > { + WTF_MAKE_NONCOPYABLE(WeakReference<T>); + WTF_MAKE_FAST_ALLOCATED; +public: + static PassRefPtr<WeakReference<T> > create(T* ptr) { return adoptRef(new WeakReference(ptr)); } + static PassRefPtr<WeakReference<T> > createUnbound() { return adoptRef(new WeakReference()); } + + T* get() const + { + ASSERT(m_boundThread == currentThread()); + return m_ptr; + } + + void clear() + { + ASSERT(m_boundThread == currentThread()); + m_ptr = 0; + } + + void bindTo(T* ptr) + { + ASSERT(!m_ptr); +#ifndef NDEBUG + m_boundThread = currentThread(); +#endif + m_ptr = ptr; + } + +private: + WeakReference() : m_ptr(0) { } + + explicit WeakReference(T* ptr) + : m_ptr(ptr) +#ifndef NDEBUG + , m_boundThread(currentThread()) +#endif + { + } + + T* m_ptr; +#ifndef NDEBUG + ThreadIdentifier m_boundThread; +#endif +}; + +template<typename T> +class WeakPtr { + WTF_MAKE_FAST_ALLOCATED; +public: + WeakPtr() { } + WeakPtr(PassRefPtr<WeakReference<T> > ref) : m_ref(ref) { } + + T* get() const { return m_ref->get(); } + +private: + RefPtr<WeakReference<T> > m_ref; +}; + +template<typename T> +class WeakPtrFactory { + WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>); + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WeakPtrFactory(T* ptr) : m_ref(WeakReference<T>::create(ptr)) { } + + WeakPtrFactory(PassRefPtr<WeakReference<T> > ref, T* ptr) + : m_ref(ref) + { + m_ref->bindTo(ptr); + } + + ~WeakPtrFactory() { m_ref->clear(); } + + // We should consider having createWeakPtr populate m_ref the first time createWeakPtr is called. + WeakPtr<T> createWeakPtr() { return WeakPtr<T>(m_ref); } + + void revokeAll() + { + T* ptr = m_ref->get(); + m_ref->clear(); + // We create a new WeakReference so that future calls to createWeakPtr() create nonzero WeakPtrs. + m_ref = WeakReference<T>::create(ptr); + } + +private: + RefPtr<WeakReference<T> > m_ref; +}; + +} // namespace WTF + +using WTF::WeakPtr; +using WTF::WeakPtrFactory; +using WTF::WeakReference; + +#endif diff --git a/Source/WTF/wtf/chromium/ChromiumThreading.h b/Source/WTF/wtf/chromium/ChromiumThreading.h deleted file mode 100644 index 39386219d..000000000 --- a/Source/WTF/wtf/chromium/ChromiumThreading.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (C) 2009 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 ChromiumThreading_h -#define ChromiumThreading_h - -namespace WTF { - -// An interface to the embedding layer, which provides threading support. -class ChromiumThreading { -public: - static void callOnMainThread(void (*func)(void*), void* context); -}; - -} // namespace WTF - -#endif // ChromiumThreading_h diff --git a/Source/WTF/wtf/chromium/MainThreadChromium.cpp b/Source/WTF/wtf/chromium/MainThreadChromium.cpp deleted file mode 100644 index 9e6592b57..000000000 --- a/Source/WTF/wtf/chromium/MainThreadChromium.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (C) 2009 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 "MainThread.h" - -#include "Assertions.h" -#include "ChromiumThreading.h" -#include "Threading.h" - -namespace WTF { - -static ThreadIdentifier mainThreadIdentifier; - -void initializeMainThread() -{ - static bool initializedMainThread; - if (initializedMainThread) - return; - initializedMainThread = true; - - mainThreadIdentifier = currentThread(); -} - -void callOnMainThread(MainThreadFunction* function, void* context) -{ - ChromiumThreading::callOnMainThread(function, context); -} - -void callOnMainThreadAndWait(MainThreadFunction*, void*) -{ - ASSERT_NOT_REACHED(); -} - -void setMainThreadCallbacksPaused(bool) -{ - ASSERT_NOT_REACHED(); -} - -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} - -} // namespace WTF - diff --git a/Source/WTF/wtf/dtoa.cpp b/Source/WTF/wtf/dtoa.cpp index cf1bc2cda..7de4172c4 100644 --- a/Source/WTF/wtf/dtoa.cpp +++ b/Source/WTF/wtf/dtoa.cpp @@ -36,7 +36,6 @@ #include "dtoa.h" #include <stdio.h> -#include <wtf/AlwaysInline.h> #include <wtf/MathExtras.h> #include <wtf/Threading.h> #include <wtf/Vector.h> @@ -742,7 +741,7 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, bool& signOut, int& exponen // roundingNone only allowed (only sensible?) with leftright set. ASSERT(!roundingNone || leftright); - ASSERT(isfinite(dd)); + ASSERT(std::isfinite(dd)); int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, j, j1, k, k0, k_check, m2, m5, s2, s5, diff --git a/Source/WTF/wtf/dtoa/bignum-dtoa.cc b/Source/WTF/wtf/dtoa/bignum-dtoa.cc index 38be56c73..b58aa1458 100644 --- a/Source/WTF/wtf/dtoa/bignum-dtoa.cc +++ b/Source/WTF/wtf/dtoa/bignum-dtoa.cc @@ -74,22 +74,22 @@ namespace double_conversion { static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, Bignum* delta_minus, Bignum* delta_plus, bool is_even, - Vector<char> buffer, int* length); + BufferReference<char> buffer, int* length); // Generates 'requested_digits' after the decimal point. static void BignumToFixed(int requested_digits, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length); + BufferReference<char>(buffer), int* length); // Generates 'count' digits of numerator/denominator. // Once 'count' digits have been produced rounds the result depending on the // remainder (remainders of exactly .5 round upwards). Might update the // decimal_point when rounding up (for example for 0.9999). static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length); + BufferReference<char>(buffer), int* length); void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, - Vector<char> buffer, int* length, int* decimal_point) { + BufferReference<char> buffer, int* length, int* decimal_point) { ASSERT(v > 0); ASSERT(!Double(v).IsSpecial()); uint64_t significand = Double(v).Significand(); @@ -171,7 +171,7 @@ namespace double_conversion { static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, Bignum* delta_minus, Bignum* delta_plus, bool is_even, - Vector<char> buffer, int* length) { + BufferReference<char> buffer, int* length) { // Small optimization: if delta_minus and delta_plus are the same just reuse // one of the two bignums. if (Bignum::Equal(*delta_minus, *delta_plus)) { @@ -268,7 +268,7 @@ namespace double_conversion { // exponent (decimal_point), when rounding upwards. static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length) { + BufferReference<char>(buffer), int* length) { ASSERT(count >= 0); for (int i = 0; i < count - 1; ++i) { uint16_t digit; @@ -310,7 +310,7 @@ namespace double_conversion { // Input verifies: 1 <= (numerator + delta) / denominator < 10. static void BignumToFixed(int requested_digits, int* decimal_point, Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length) { + BufferReference<char>(buffer), int* length) { // Note that we have to look at more than just the requested_digits, since // a number could be rounded up. Example: v=0.5 with requested_digits=0. // Even though the power of v equals 0 we can't just stop here. diff --git a/Source/WTF/wtf/dtoa/bignum-dtoa.h b/Source/WTF/wtf/dtoa/bignum-dtoa.h index 076168709..45b7efebb 100644 --- a/Source/WTF/wtf/dtoa/bignum-dtoa.h +++ b/Source/WTF/wtf/dtoa/bignum-dtoa.h @@ -77,7 +77,7 @@ namespace double_conversion { // 'BignumDtoa' expects the given buffer to be big enough to hold all digits // and a terminating null-character. void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, - Vector<char> buffer, int* length, int* point); + BufferReference<char> buffer, int* length, int* point); } // namespace double_conversion diff --git a/Source/WTF/wtf/dtoa/bignum.cc b/Source/WTF/wtf/dtoa/bignum.cc index 46a900a85..9bb9049a2 100644 --- a/Source/WTF/wtf/dtoa/bignum.cc +++ b/Source/WTF/wtf/dtoa/bignum.cc @@ -68,7 +68,7 @@ namespace double_conversion { int needed_bigits = kUInt64Size / kBigitSize + 1; EnsureCapacity(needed_bigits); for (int i = 0; i < needed_bigits; ++i) { - bigits_[i] = (uint32_t)value & kBigitMask; + bigits_[i] = static_cast<Chunk>(value & kBigitMask); value = value >> kBigitSize; } used_digits_ = needed_bigits; @@ -89,7 +89,7 @@ namespace double_conversion { } - static uint64_t ReadUInt64(Vector<const char> buffer, + static uint64_t ReadUInt64(BufferReference<const char> buffer, int from, int digits_to_read) { uint64_t result = 0; @@ -102,7 +102,7 @@ namespace double_conversion { } - void Bignum::AssignDecimalString(Vector<const char> value) { + void Bignum::AssignDecimalString(BufferReference<const char> value) { // 2^64 = 18446744073709551616 > 10^19 const int kMaxUint64DecimalDigits = 19; Zero(); @@ -132,7 +132,7 @@ namespace double_conversion { } - void Bignum::AssignHexString(Vector<const char> value) { + void Bignum::AssignHexString(BufferReference<const char> value) { Zero(); int length = value.length(); @@ -267,7 +267,7 @@ namespace double_conversion { } while (carry != 0) { EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = (uint32_t)carry & kBigitMask; + bigits_[used_digits_] = static_cast<Chunk>(carry & kBigitMask); used_digits_++; carry >>= kBigitSize; } @@ -288,13 +288,13 @@ namespace double_conversion { uint64_t product_low = low * bigits_[i]; uint64_t product_high = high * bigits_[i]; uint64_t tmp = (carry & kBigitMask) + product_low; - bigits_[i] = (uint32_t)tmp & kBigitMask; + bigits_[i] = static_cast<Chunk>(tmp & kBigitMask); carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + (product_high << (32 - kBigitSize)); } while (carry != 0) { EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = (uint32_t)carry & kBigitMask; + bigits_[used_digits_] = static_cast<Chunk>(carry & kBigitMask); used_digits_++; carry >>= kBigitSize; } @@ -737,6 +737,13 @@ namespace double_conversion { void Bignum::SubtractTimes(const Bignum& other, int factor) { +#ifndef NDEBUG + Bignum a, b; + a.AssignBignum(*this); + b.AssignBignum(other); + b.MultiplyByUInt32(factor); + a.SubtractBignum(b); +#endif ASSERT(exponent_ <= other.exponent_); if (factor < 3) { for (int i = 0; i < factor; ++i) { @@ -749,7 +756,8 @@ namespace double_conversion { for (int i = 0; i < other.used_digits_; ++i) { DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i]; DoubleChunk remove = borrow + product; - Chunk difference = bigits_[i + exponent_diff] - ((uint32_t)remove & kBigitMask); + Chunk difference = + bigits_[i + exponent_diff] - static_cast<Chunk>(remove & kBigitMask); bigits_[i + exponent_diff] = difference & kBigitMask; borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) + (remove >> kBigitSize)); @@ -759,9 +767,9 @@ namespace double_conversion { Chunk difference = bigits_[i] - borrow; bigits_[i] = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); - ++i; } Clamp(); + ASSERT(Bignum::Equal(a, *this)); } diff --git a/Source/WTF/wtf/dtoa/bignum.h b/Source/WTF/wtf/dtoa/bignum.h index 1a750581a..02e6a4929 100644 --- a/Source/WTF/wtf/dtoa/bignum.h +++ b/Source/WTF/wtf/dtoa/bignum.h @@ -46,8 +46,8 @@ namespace double_conversion { void AssignUInt64(uint64_t value); void AssignBignum(const Bignum& other); - void AssignDecimalString(Vector<const char> value); - void AssignHexString(Vector<const char> value); + void AssignDecimalString(BufferReference<const char> value); + void AssignHexString(BufferReference<const char> value); void AssignPowerUInt16(uint16_t base, int exponent); @@ -130,7 +130,7 @@ namespace double_conversion { Chunk bigits_buffer_[kBigitCapacity]; // A vector backed by bigits_buffer_. This way accesses to the array are // checked for out-of-bounds errors. - Vector<Chunk> bigits_; + BufferReference<Chunk> bigits_; int used_digits_; // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). int exponent_; diff --git a/Source/WTF/wtf/dtoa/cached-powers.cc b/Source/WTF/wtf/dtoa/cached-powers.cc index 54cb7cadd..16f4c91f6 100644 --- a/Source/WTF/wtf/dtoa/cached-powers.cc +++ b/Source/WTF/wtf/dtoa/cached-powers.cc @@ -31,7 +31,6 @@ #include <limits.h> #include <math.h> -#include "UnusedParam.h" #include "utils.h" #include "cached-powers.h" diff --git a/Source/WTF/wtf/dtoa/cached-powers.h b/Source/WTF/wtf/dtoa/cached-powers.h index cbc04d43d..6ccfd2536 100644 --- a/Source/WTF/wtf/dtoa/cached-powers.h +++ b/Source/WTF/wtf/dtoa/cached-powers.h @@ -63,7 +63,7 @@ namespace double_conversion { // Initializes the table of cached powers used by the dtoa algorithm. // This needs to be called when JSC is being initialized. - void initialize(); + WTF_EXPORT_PRIVATE void initialize(); } // namespace double_conversion diff --git a/Source/WTF/wtf/dtoa/double-conversion.cc b/Source/WTF/wtf/dtoa/double-conversion.cc index c46dba98b..5ab502497 100644 --- a/Source/WTF/wtf/dtoa/double-conversion.cc +++ b/Source/WTF/wtf/dtoa/double-conversion.cc @@ -360,7 +360,7 @@ namespace double_conversion { bool* sign, int* length, int* point) { - Vector<char> vector(buffer, buffer_length); + BufferReference<char> vector(buffer, buffer_length); ASSERT(!Double(v).IsSpecial()); ASSERT(mode == SHORTEST || requested_digits >= 0); @@ -596,7 +596,7 @@ namespace double_conversion { ASSERT(buffer_pos < kBufferSize); buffer[buffer_pos] = '\0'; - double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); + double converted = Strtod(BufferReference<const char>(buffer, buffer_pos), exponent); *processed_characters_count = current - input; return sign? -converted: converted; } diff --git a/Source/WTF/wtf/dtoa/double-conversion.h b/Source/WTF/wtf/dtoa/double-conversion.h index eb26e87b3..cf49c0d7c 100644 --- a/Source/WTF/wtf/dtoa/double-conversion.h +++ b/Source/WTF/wtf/dtoa/double-conversion.h @@ -131,7 +131,7 @@ namespace double_conversion { } // Returns a converter following the EcmaScript specification. - static const DoubleToStringConverter& EcmaScriptConverter(); + WTF_EXPORT_PRIVATE static const DoubleToStringConverter& EcmaScriptConverter(); // Computes the shortest string of digits that correctly represent the input // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high @@ -224,7 +224,7 @@ namespace double_conversion { // kMaxExponentialDigits + 8 characters (the sign, the digit before the // decimal point, the decimal point, the exponent character, the // exponent's sign, and at most 3 exponent digits). - bool ToExponential(double value, + WTF_EXPORT_PRIVATE bool ToExponential(double value, int requested_digits, StringBuilder* result_builder) const; diff --git a/Source/WTF/wtf/dtoa/fast-dtoa.cc b/Source/WTF/wtf/dtoa/fast-dtoa.cc index 9d9872417..45cec68aa 100644 --- a/Source/WTF/wtf/dtoa/fast-dtoa.cc +++ b/Source/WTF/wtf/dtoa/fast-dtoa.cc @@ -62,7 +62,7 @@ namespace double_conversion { // Output: returns true if the buffer is guaranteed to contain the closest // representable number to the input. // Modifies the generated digits in the buffer to approach (round towards) w. - static bool RoundWeed(Vector<char> buffer, + static bool RoundWeed(BufferReference<char> buffer, int length, uint64_t distance_too_high_w, uint64_t unsafe_interval, @@ -182,7 +182,7 @@ namespace double_conversion { // unambiguously determined. // // Precondition: rest < ten_kappa. - static bool RoundWeedCounted(Vector<char> buffer, + static bool RoundWeedCounted(BufferReference<char> buffer, int length, uint64_t rest, uint64_t ten_kappa, @@ -386,7 +386,7 @@ namespace double_conversion { static bool DigitGen(DiyFp low, DiyFp w, DiyFp high, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* kappa) { ASSERT(low.e() == w.e() && w.e() == high.e()); @@ -511,7 +511,7 @@ namespace double_conversion { // increases with higher requested_digits. static bool DigitGenCounted(DiyFp w, int requested_digits, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* kappa) { ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); @@ -599,7 +599,7 @@ namespace double_conversion { // digits might correctly yield 'v' when read again, the closest will be // computed. static bool Grisu3(double v, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* decimal_exponent) { DiyFp w = Double(v).AsNormalizedDiyFp(); @@ -665,7 +665,7 @@ namespace double_conversion { // therefore the rounding strategy for halfway cases is irrelevant. static bool Grisu3Counted(double v, int requested_digits, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* decimal_exponent) { DiyFp w = Double(v).AsNormalizedDiyFp(); @@ -710,7 +710,7 @@ namespace double_conversion { bool FastDtoa(double v, FastDtoaMode mode, int requested_digits, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* decimal_point) { ASSERT(v > 0); diff --git a/Source/WTF/wtf/dtoa/fast-dtoa.h b/Source/WTF/wtf/dtoa/fast-dtoa.h index 876a9f382..e1443237f 100644 --- a/Source/WTF/wtf/dtoa/fast-dtoa.h +++ b/Source/WTF/wtf/dtoa/fast-dtoa.h @@ -77,7 +77,7 @@ namespace double_conversion { bool FastDtoa(double d, FastDtoaMode mode, int requested_digits, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* decimal_point); diff --git a/Source/WTF/wtf/dtoa/fixed-dtoa.cc b/Source/WTF/wtf/dtoa/fixed-dtoa.cc index 40b7180e5..45ba73c0a 100644 --- a/Source/WTF/wtf/dtoa/fixed-dtoa.cc +++ b/Source/WTF/wtf/dtoa/fixed-dtoa.cc @@ -29,7 +29,6 @@ #include <math.h> -#include "UnusedParam.h" #include "fixed-dtoa.h" #include "double.h" @@ -123,7 +122,7 @@ namespace double_conversion { static void FillDigits32FixedLength(uint32_t number, int requested_length, - Vector<char> buffer, int* length) { + BufferReference<char> buffer, int* length) { for (int i = requested_length - 1; i >= 0; --i) { buffer[(*length) + i] = '0' + number % 10; number /= 10; @@ -132,7 +131,7 @@ namespace double_conversion { } - static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) { + static void FillDigits32(uint32_t number, BufferReference<char> buffer, int* length) { int number_length = 0; // We fill the digits in reverse order and exchange them afterwards. while (number != 0) { @@ -156,7 +155,7 @@ namespace double_conversion { static void FillDigits64FixedLength(uint64_t number, int requested_length, - Vector<char> buffer, int* length) { + BufferReference<char> buffer, int* length) { UNUSED_PARAM(requested_length); const uint32_t kTen7 = 10000000; // For efficiency cut the number into 3 uint32_t parts, and print those. @@ -171,7 +170,7 @@ namespace double_conversion { } - static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) { + static void FillDigits64(uint64_t number, BufferReference<char> buffer, int* length) { const uint32_t kTen7 = 10000000; // For efficiency cut the number into 3 uint32_t parts, and print those. uint32_t part2 = static_cast<uint32_t>(number % kTen7); @@ -192,7 +191,7 @@ namespace double_conversion { } - static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) { + static void RoundUp(BufferReference<char> buffer, int* length, int* decimal_point) { // An empty buffer represents 0. if (*length == 0) { buffer[0] = '1'; @@ -234,7 +233,7 @@ namespace double_conversion { // already contained "199" (thus yielding a buffer of "19999") then a // rounding-up will change the contents of the buffer to "20000". static void FillFractionals(uint64_t fractionals, int exponent, - int fractional_count, Vector<char> buffer, + int fractional_count, BufferReference<char> buffer, int* length, int* decimal_point) { ASSERT(-128 <= exponent && exponent <= 0); // 'fractionals' is a fixed-point number, with binary point at bit @@ -292,7 +291,7 @@ namespace double_conversion { // Removes leading and trailing zeros. // If leading zeros are removed then the decimal point position is adjusted. - static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) { + static void TrimZeros(BufferReference<char> buffer, int* length, int* decimal_point) { while (*length > 0 && buffer[(*length) - 1] == '0') { (*length)--; } @@ -312,7 +311,7 @@ namespace double_conversion { bool FastFixedDtoa(double v, int fractional_count, - Vector<char> buffer, + BufferReference<char> buffer, int* length, int* decimal_point) { const uint32_t kMaxUInt32 = 0xFFFFFFFF; diff --git a/Source/WTF/wtf/dtoa/fixed-dtoa.h b/Source/WTF/wtf/dtoa/fixed-dtoa.h index 8c0adb758..c39133235 100644 --- a/Source/WTF/wtf/dtoa/fixed-dtoa.h +++ b/Source/WTF/wtf/dtoa/fixed-dtoa.h @@ -51,7 +51,7 @@ namespace double_conversion { // This method only works for some parameters. If it can't handle the input it // returns false. The output is null-terminated when the function succeeds. bool FastFixedDtoa(double v, int fractional_count, - Vector<char> buffer, int* length, int* decimal_point); + BufferReference<char> buffer, int* length, int* decimal_point); } // namespace double_conversion diff --git a/Source/WTF/wtf/dtoa/strtod.cc b/Source/WTF/wtf/dtoa/strtod.cc index 477e7158c..5f63b22ad 100644 --- a/Source/WTF/wtf/dtoa/strtod.cc +++ b/Source/WTF/wtf/dtoa/strtod.cc @@ -92,27 +92,27 @@ namespace double_conversion { // we round up to 780. static const int kMaxSignificantDecimalDigits = 780; - static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) { + static BufferReference<const char> TrimLeadingZeros(BufferReference<const char> buffer) { for (int i = 0; i < buffer.length(); i++) { if (buffer[i] != '0') { - return buffer.SubVector(i, buffer.length()); + return buffer.SubBufferReference(i, buffer.length()); } } - return Vector<const char>(buffer.start(), 0); + return BufferReference<const char>(buffer.start(), 0); } - static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { + static BufferReference<const char> TrimTrailingZeros(BufferReference<const char> buffer) { for (int i = buffer.length() - 1; i >= 0; --i) { if (buffer[i] != '0') { - return buffer.SubVector(0, i + 1); + return buffer.SubBufferReference(0, i + 1); } } - return Vector<const char>(buffer.start(), 0); + return BufferReference<const char>(buffer.start(), 0); } - static void TrimToMaxSignificantDigits(Vector<const char> buffer, + static void TrimToMaxSignificantDigits(BufferReference<const char> buffer, int exponent, char* significant_buffer, int* significant_exponent) { @@ -134,7 +134,7 @@ namespace double_conversion { // When the string starts with "1844674407370955161" no further digit is read. // Since 2^64 = 18446744073709551616 it would still be possible read another // digit if it was less or equal than 6, but this would complicate the code. - static uint64_t ReadUint64(Vector<const char> buffer, + static uint64_t ReadUint64(BufferReference<const char> buffer, int* number_of_read_digits) { uint64_t result = 0; int i = 0; @@ -152,7 +152,7 @@ namespace double_conversion { // The returned DiyFp is not necessarily normalized. // If remaining_decimals is zero then the returned DiyFp is accurate. // Otherwise it has been rounded and has error of at most 1/2 ulp. - static void ReadDiyFp(Vector<const char> buffer, + static void ReadDiyFp(BufferReference<const char> buffer, DiyFp* result, int* remaining_decimals) { int read_digits; @@ -173,7 +173,7 @@ namespace double_conversion { } - static bool DoubleStrtod(Vector<const char> trimmed, + static bool DoubleStrtod(BufferReference<const char> trimmed, int exponent, double* result) { #if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) @@ -251,7 +251,7 @@ namespace double_conversion { // If the function returns true then the result is the correct double. // Otherwise it is either the correct double or the double that is just below // the correct double. - static bool DiyFpStrtod(Vector<const char> buffer, + static bool DiyFpStrtod(BufferReference<const char> buffer, int exponent, double* result) { DiyFp input; @@ -368,7 +368,7 @@ namespace double_conversion { // buffer.length() + exponent <= kMaxDecimalPower + 1 // buffer.length() + exponent > kMinDecimalPower // buffer.length() <= kMaxDecimalSignificantDigits - static double BignumStrtod(Vector<const char> buffer, + static double BignumStrtod(BufferReference<const char> buffer, int exponent, double guess) { if (guess == Double::Infinity()) { @@ -413,9 +413,9 @@ namespace double_conversion { } - double Strtod(Vector<const char> buffer, int exponent) { - Vector<const char> left_trimmed = TrimLeadingZeros(buffer); - Vector<const char> trimmed = TrimTrailingZeros(left_trimmed); + double Strtod(BufferReference<const char> buffer, int exponent) { + BufferReference<const char> left_trimmed = TrimLeadingZeros(buffer); + BufferReference<const char> trimmed = TrimTrailingZeros(left_trimmed); exponent += left_trimmed.length() - trimmed.length(); if (trimmed.length() == 0) return 0.0; if (trimmed.length() > kMaxSignificantDecimalDigits) { @@ -423,7 +423,7 @@ namespace double_conversion { int significant_exponent; TrimToMaxSignificantDigits(trimmed, exponent, significant_buffer, &significant_exponent); - return Strtod(Vector<const char>(significant_buffer, + return Strtod(BufferReference<const char>(significant_buffer, kMaxSignificantDecimalDigits), significant_exponent); } diff --git a/Source/WTF/wtf/dtoa/strtod.h b/Source/WTF/wtf/dtoa/strtod.h index 8ed350ad8..66973cebf 100644 --- a/Source/WTF/wtf/dtoa/strtod.h +++ b/Source/WTF/wtf/dtoa/strtod.h @@ -36,7 +36,7 @@ namespace double_conversion { // The buffer must only contain digits in the range [0-9]. It must not // contain a dot or a sign. It must not start with '0', and must not be empty. - double Strtod(Vector<const char> buffer, int exponent); + double Strtod(BufferReference<const char> buffer, int exponent); } // namespace double_conversion diff --git a/Source/WTF/wtf/dtoa/utils.h b/Source/WTF/wtf/dtoa/utils.h index da6e13226..e2f0a405c 100644 --- a/Source/WTF/wtf/dtoa/utils.h +++ b/Source/WTF/wtf/dtoa/utils.h @@ -136,23 +136,24 @@ namespace double_conversion { ASSERT(length == static_cast<size_t>(static_cast<int>(length))); return static_cast<int>(length); } - - // This is a simplified version of V8's Vector class. + + // BufferReference abstract a memory buffer. It provides a pointer + // to the beginning of the buffer, and the available length. template <typename T> - class Vector { + class BufferReference { public: - Vector() : start_(NULL), length_(0) {} - Vector(T* data, int length) : start_(data), length_(length) { + BufferReference() : start_(NULL), length_(0) {} + BufferReference(T* data, int length) : start_(data), length_(length) { ASSERT(length == 0 || (length > 0 && data != NULL)); } // Returns a vector using the same backing storage as this one, // spanning from and including 'from', to but not including 'to'. - Vector<T> SubVector(int from, int to) { + BufferReference<T> SubBufferReference(int from, int to) { ASSERT(to <= length_); ASSERT(from < to); ASSERT(0 <= from); - return Vector<T>(start() + from, to - from); + return BufferReference<T>(start() + from, to - from); } // Returns the length of the vector. @@ -202,7 +203,7 @@ namespace double_conversion { void SetPosition(int position) { ASSERT(!is_finalized()); - ASSERT(position < size()); + ASSERT_WITH_SECURITY_IMPLICATION(position < size()); position_ = position; } @@ -228,7 +229,7 @@ namespace double_conversion { // builder. The input string must have enough characters. void AddSubstring(const char* s, int n) { ASSERT(!is_finalized() && position_ + n < buffer_.length()); - ASSERT(static_cast<size_t>(n) <= strlen(s)); + ASSERT_WITH_SECURITY_IMPLICATION(static_cast<size_t>(n) <= strlen(s)); memcpy(&buffer_[position_], s, n * kCharSize); position_ += n; } @@ -255,7 +256,7 @@ namespace double_conversion { } private: - Vector<char> buffer_; + BufferReference<char> buffer_; int position_; bool is_finalized() const { return position_ < 0; } diff --git a/Source/WTF/wtf/efl/OwnPtrEfl.cpp b/Source/WTF/wtf/efl/OwnPtrEfl.cpp index 59c8ad5c3..4b289f859 100644 --- a/Source/WTF/wtf/efl/OwnPtrEfl.cpp +++ b/Source/WTF/wtf/efl/OwnPtrEfl.cpp @@ -63,12 +63,6 @@ void deleteOwnedPtr(Eina_Module* ptr) eina_module_free(ptr); // If module wasn't unloaded, eina_module_free() calls eina_module_unload(). } -void deleteOwnedPtr(Ecore_Timer* ptr) -{ - if (ptr) - ecore_timer_del(ptr); -} - void deleteOwnedPtr(Ecore_IMF_Context* ptr) { if (ptr) diff --git a/Source/WTF/wtf/efl/RefPtrEfl.h b/Source/WTF/wtf/efl/RefPtrEfl.h index 48152842d..ab564357f 100644 --- a/Source/WTF/wtf/efl/RefPtrEfl.h +++ b/Source/WTF/wtf/efl/RefPtrEfl.h @@ -22,7 +22,11 @@ #include <wtf/RefPtr.h> +#if USE(EO) +typedef struct _Eo Evas_Object; +#else typedef struct _Evas_Object Evas_Object; +#endif namespace WTF { diff --git a/Source/WTF/wtf/gobject/GMutexLocker.h b/Source/WTF/wtf/gobject/GMutexLocker.h new file mode 100644 index 000000000..9800dd95c --- /dev/null +++ b/Source/WTF/wtf/gobject/GMutexLocker.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GMutexLocker_h +#define GMutexLocker_h + +#if USE(GLIB) + +#include <glib.h> + +#include <wtf/FastAllocBase.h> +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class GMutexLocker { + WTF_MAKE_NONCOPYABLE(GMutexLocker); WTF_MAKE_FAST_ALLOCATED; + +public: + inline explicit GMutexLocker(GMutex* mutex) + : m_mutex(mutex) + , m_val(0) + { + lock(); + } + + inline ~GMutexLocker() { unlock(); } + + inline void lock() + { + if (m_mutex && !m_val) { + g_mutex_lock(m_mutex); + m_val = 1; + } + } + + inline void unlock() + { + if (m_mutex && m_val) { + m_val = 0; + g_mutex_unlock(m_mutex); + } + } + + inline GMutex* mutex() const { return m_mutex; } + +private: + GMutex* m_mutex; + uint8_t m_val; +}; + +} + +#endif // USE(GLIB) + +#endif // GMutexLocker_h diff --git a/Source/WTF/wtf/gobject/GOwnPtr.cpp b/Source/WTF/wtf/gobject/GOwnPtr.cpp index dfe187d78..312dcff4a 100644 --- a/Source/WTF/wtf/gobject/GOwnPtr.cpp +++ b/Source/WTF/wtf/gobject/GOwnPtr.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "GOwnPtr.h" -#if ENABLE(GLIB_SUPPORT) +#if USE(GLIB) #include <gio/gio.h> #include <glib.h> @@ -68,4 +68,4 @@ template <> void freeOwnedGPtr<GKeyFile>(GKeyFile* ptr) } // namespace WTF -#endif // ENABLE(GLIB_SUPPORT) +#endif // USE(GLIB) diff --git a/Source/WTF/wtf/gobject/GOwnPtr.h b/Source/WTF/wtf/gobject/GOwnPtr.h index 4b2dcb77b..024130232 100644 --- a/Source/WTF/wtf/gobject/GOwnPtr.h +++ b/Source/WTF/wtf/gobject/GOwnPtr.h @@ -22,7 +22,7 @@ #ifndef GOwnPtr_h #define GOwnPtr_h -#if ENABLE(GLIB_SUPPORT) +#if USE(GLIB) #include <algorithm> #include <wtf/Assertions.h> @@ -138,7 +138,7 @@ template <typename T> inline void freeOwnedGPtr(T* ptr) using WTF::GOwnPtr; -#endif // ENABLE(GLIB_SUPPORT) +#endif // USE(GLIB) #endif // GOwnPtr_h diff --git a/Source/WTF/wtf/gobject/GRefPtr.cpp b/Source/WTF/wtf/gobject/GRefPtr.cpp index 79e967c25..3931d5aff 100644 --- a/Source/WTF/wtf/gobject/GRefPtr.cpp +++ b/Source/WTF/wtf/gobject/GRefPtr.cpp @@ -19,7 +19,7 @@ #include "config.h" #include "GRefPtr.h" -#if ENABLE(GLIB_SUPPORT) +#if USE(GLIB) #include <glib.h> @@ -94,7 +94,6 @@ template <> void derefGPtr(GBytes* ptr) #endif -#if GLIB_CHECK_VERSION(2, 24, 0) template <> GVariant* refGPtr(GVariant* ptr) { if (ptr) @@ -107,24 +106,6 @@ template <> void derefGPtr(GVariant* ptr) g_variant_unref(ptr); } -#else - -// We do this so that we can avoid including the glib.h header in GRefPtr.h. -typedef struct _GVariant { - bool fake; -} GVariant; - -template <> GVariant* refGPtr(GVariant* ptr) -{ - return ptr; -} - -template <> void derefGPtr(GVariant* ptr) -{ -} - -#endif - template <> GSource* refGPtr(GSource* ptr) { if (ptr) @@ -166,4 +147,4 @@ template <> void derefGPtr(GByteArray* ptr) } // namespace WTF -#endif // ENABLE(GLIB_SUPPORT) +#endif // USE(GLIB) diff --git a/Source/WTF/wtf/gobject/GRefPtr.h b/Source/WTF/wtf/gobject/GRefPtr.h index b0909b679..6c50f4da4 100644 --- a/Source/WTF/wtf/gobject/GRefPtr.h +++ b/Source/WTF/wtf/gobject/GRefPtr.h @@ -23,9 +23,8 @@ #ifndef WTF_GRefPtr_h #define WTF_GRefPtr_h -#if ENABLE(GLIB_SUPPORT) +#if USE(GLIB) -#include <wtf/AlwaysInline.h> #include <wtf/RefPtr.h> #include <algorithm> @@ -233,6 +232,6 @@ template <typename T> inline void derefGPtr(T* ptr) using WTF::GRefPtr; using WTF::adoptGRef; -#endif // ENABLE(GLIB_SUPPORT) +#endif // USE(GLIB) #endif // WTF_GRefPtr_h diff --git a/Source/WTF/wtf/mac/MainThreadMac.mm b/Source/WTF/wtf/mac/MainThreadMac.mm index 5a82f40a6..eff969192 100644 --- a/Source/WTF/wtf/mac/MainThreadMac.mm +++ b/Source/WTF/wtf/mac/MainThreadMac.mm @@ -70,6 +70,7 @@ void initializeMainThreadPlatform() initializeGCThreads(); } +#if !USE(WEB_THREAD) void initializeMainThreadToProcessMainThreadPlatform() { if (!pthread_main_np()) @@ -84,6 +85,7 @@ void initializeMainThreadToProcessMainThreadPlatform() initializeGCThreads(); } +#endif // !USE(WEB_THREAD) static void timerFired(CFRunLoopTimerRef timer, void*) { @@ -133,4 +135,16 @@ bool isMainThread() return pthread_equal(pthread_self(), mainThreadPthread); } +#if USE(WEB_THREAD) +bool isUIThread() +{ + return pthread_main_np(); +} + +bool isWebThread() +{ + return pthread_equal(pthread_self(), mainThreadPthread); +} +#endif // USE(WEB_THREAD) + } // namespace WTF diff --git a/Source/WTF/wtf/text/ASCIIFastPath.h b/Source/WTF/wtf/text/ASCIIFastPath.h index 0233efc6e..e266afd1e 100644 --- a/Source/WTF/wtf/text/ASCIIFastPath.h +++ b/Source/WTF/wtf/text/ASCIIFastPath.h @@ -27,6 +27,7 @@ #endif #include <stdint.h> #include <wtf/Alignment.h> +#include <wtf/StdLibExtras.h> #include <wtf/unicode/Unicode.h> namespace WTF { @@ -85,7 +86,7 @@ inline bool charactersAreAllASCII(const CharacterType* characters, size_t length const CharacterType* wordEnd = alignToMachineWord(end); const size_t loopIncrement = sizeof(MachineWord) / sizeof(CharacterType); while (characters < wordEnd) { - allCharBits |= *(reinterpret_cast<const MachineWord*>(characters)); + allCharBits |= *(reinterpret_cast_ptr<const MachineWord*>(characters)); characters += loopIncrement; } @@ -112,9 +113,9 @@ inline void copyLCharsFromUCharSource(LChar* destination, const UChar* source, s } const uintptr_t sourceLoadSize = 32; // Process 32 bytes (16 UChars) each iteration - const unsigned ucharsPerLoop = sourceLoadSize / sizeof(UChar); + const size_t ucharsPerLoop = sourceLoadSize / sizeof(UChar); if (length > ucharsPerLoop) { - const unsigned endLength = length - ucharsPerLoop + 1; + const size_t endLength = length - ucharsPerLoop + 1; for (; i < endLength; i += ucharsPerLoop) { #ifndef NDEBUG for (unsigned checkIndex = 0; checkIndex < ucharsPerLoop; ++checkIndex) @@ -138,9 +139,8 @@ inline void copyLCharsFromUCharSource(LChar* destination, const UChar* source, s if (length >= (2 * memoryAccessSize) - 1) { // Prefix: align dst on 64 bits. const uintptr_t memoryAccessMask = memoryAccessSize - 1; - do { + while (!isAlignedTo<memoryAccessMask>(destination)) *destination++ = static_cast<LChar>(*source++); - } while (!isAlignedTo<memoryAccessMask>(destination)); // Vector interleaved unpack, we only store the lower 8 bits. const uintptr_t lengthLeft = end - destination; diff --git a/Source/WTF/wtf/text/AtomicString.cpp b/Source/WTF/wtf/text/AtomicString.cpp index 8732ea84f..8103081b0 100644 --- a/Source/WTF/wtf/text/AtomicString.cpp +++ b/Source/WTF/wtf/text/AtomicString.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved. * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> * Copyright (C) 2012 Google Inc. All rights reserved. * @@ -24,62 +24,58 @@ #include "AtomicString.h" +#include "AtomicStringTable.h" #include "StringHash.h" #include <wtf/HashSet.h> #include <wtf/Threading.h> #include <wtf/WTFThreadData.h> #include <wtf/unicode/UTF8.h> +#if USE(WEB_THREAD) +#include <wtf/MainThread.h> +#include <wtf/TCSpinLock.h> +#endif + namespace WTF { using namespace Unicode; COMPILE_ASSERT(sizeof(AtomicString) == sizeof(String), atomic_string_and_string_must_be_same_size); -class AtomicStringTable { - WTF_MAKE_FAST_ALLOCATED; -public: - static AtomicStringTable* create() - { - AtomicStringTable* table = new AtomicStringTable; - - WTFThreadData& data = wtfThreadData(); - data.m_atomicStringTable = table; - data.m_atomicStringTableDestructor = AtomicStringTable::destroy; - - return table; - } +#if USE(WEB_THREAD) +class AtomicStringTableLocker : public SpinLockHolder { + WTF_MAKE_NONCOPYABLE(AtomicStringTableLocker); - HashSet<StringImpl*>& table() + static SpinLock s_stringTableLock; +public: + AtomicStringTableLocker() + : SpinLockHolder(&s_stringTableLock) { - return m_table; } +}; -private: - static void destroy(AtomicStringTable* table) - { - HashSet<StringImpl*>::iterator end = table->m_table.end(); - for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) - (*iter)->setIsAtomic(false); - delete table; - } +SpinLock AtomicStringTableLocker::s_stringTableLock = SPINLOCK_INITIALIZER; +#else - HashSet<StringImpl*> m_table; +class AtomicStringTableLocker { + WTF_MAKE_NONCOPYABLE(AtomicStringTableLocker); +public: + AtomicStringTableLocker() { } + ~AtomicStringTableLocker() { } }; +#endif // USE(WEB_THREAD) -static inline HashSet<StringImpl*>& stringTable() +static ALWAYS_INLINE HashSet<StringImpl*>& stringTable() { - // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor). - AtomicStringTable* table = wtfThreadData().atomicStringTable(); - if (UNLIKELY(!table)) - table = AtomicStringTable::create(); - return table->table(); + return wtfThreadData().atomicStringTable()->table(); } template<typename T, typename HashTranslator> static inline PassRefPtr<StringImpl> addToStringTable(const T& value) { - HashSet<StringImpl*>::AddResult addResult = stringTable().add<T, HashTranslator>(value); + AtomicStringTableLocker locker; + + HashSet<StringImpl*>::AddResult addResult = stringTable().add<HashTranslator>(value); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. @@ -381,22 +377,29 @@ PassRefPtr<StringImpl> AtomicString::addFromLiteralData(const char* characters, return addToStringTable<CharBuffer, CharBufferFromLiteralDataTranslator>(buffer); } -PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r) +PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* string) { - if (!r->length()) + if (!string->length()) return StringImpl::empty(); - StringImpl* result = *stringTable().add(r).iterator; - if (result == r) - r->setIsAtomic(true); - return result; + ASSERT_WITH_MESSAGE(!string->isAtomic(), "AtomicString should not hit the slow case if the string is already atomic."); + + AtomicStringTableLocker locker; + HashSet<StringImpl*>::AddResult addResult = stringTable().add(string); + + if (addResult.isNewEntry) { + ASSERT(*addResult.iterator == string); + string->setIsAtomic(true); + } + + return *addResult.iterator; } template<typename CharacterType> static inline HashSet<StringImpl*>::iterator findString(const StringImpl* stringImpl) { HashAndCharacters<CharacterType> buffer = { stringImpl->existingHash(), stringImpl->getCharacters<CharacterType>(), stringImpl->length() }; - return stringTable().find<HashAndCharacters<CharacterType>, HashAndCharactersTranslator<CharacterType> >(buffer); + return stringTable().find<HashAndCharactersTranslator<CharacterType> >(buffer); } AtomicStringImpl* AtomicString::find(const StringImpl* stringImpl) @@ -407,6 +410,7 @@ AtomicStringImpl* AtomicString::find(const StringImpl* stringImpl) if (!stringImpl->length()) return static_cast<AtomicStringImpl*>(StringImpl::empty()); + AtomicStringTableLocker locker; HashSet<StringImpl*>::iterator iterator; if (stringImpl->is8Bit()) iterator = findString<LChar>(stringImpl); @@ -417,9 +421,14 @@ AtomicStringImpl* AtomicString::find(const StringImpl* stringImpl) return static_cast<AtomicStringImpl*>(*iterator); } -void AtomicString::remove(StringImpl* r) +void AtomicString::remove(StringImpl* string) { - stringTable().remove(r); + ASSERT(string->isAtomic()); + AtomicStringTableLocker locker; + HashSet<StringImpl*>& atomicStringTable = stringTable(); + HashSet<StringImpl*>::iterator iterator = atomicStringTable.find(string); + ASSERT_WITH_MESSAGE(iterator != atomicStringTable.end(), "The string being removed is atomic in the string table of an other thread!"); + atomicStringTable.remove(iterator); } AtomicString AtomicString::lower() const @@ -427,11 +436,15 @@ AtomicString AtomicString::lower() const // Note: This is a hot function in the Dromaeo benchmark. StringImpl* impl = this->impl(); if (UNLIKELY(!impl)) - return *this; - RefPtr<StringImpl> newImpl = impl->lower(); - if (LIKELY(newImpl == impl)) - return *this; - return AtomicString(newImpl); + return AtomicString(); + + RefPtr<StringImpl> lowerImpl = impl->lower(); + AtomicString returnValue; + if (LIKELY(lowerImpl == impl)) + returnValue.m_string = lowerImpl.release(); + else + returnValue.m_string = addSlowCase(lowerImpl.get()); + return returnValue; } AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd) @@ -448,6 +461,14 @@ AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const c return atomicString; } +#if !ASSERT_DISABLED +bool AtomicString::isInAtomicStringTable(StringImpl* string) +{ + AtomicStringTableLocker locker; + return stringTable().contains(string); +} +#endif + #ifndef NDEBUG void AtomicString::show() const { diff --git a/Source/WTF/wtf/text/AtomicString.h b/Source/WTF/wtf/text/AtomicString.h index 8aea58507..a63d6c08d 100644 --- a/Source/WTF/wtf/text/AtomicString.h +++ b/Source/WTF/wtf/text/AtomicString.h @@ -21,6 +21,7 @@ #ifndef AtomicString_h #define AtomicString_h +#include <utility> #include <wtf/text/AtomicStringImpl.h> #include <wtf/text/WTFString.h> @@ -35,7 +36,6 @@ namespace WTF { struct AtomicStringHash; -class MemoryObjectInfo; class AtomicString { public: @@ -48,6 +48,13 @@ public: AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { } AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { } AtomicString(const UChar* s) : m_string(add(s)) { } + + template<size_t inlineCapacity> + explicit AtomicString(const Vector<UChar, inlineCapacity>& characters) + : m_string(add(characters.data(), characters.size())) + { + } + ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { } AtomicString(AtomicStringImpl* imp) : m_string(imp) { } ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { } @@ -58,6 +65,7 @@ public: : m_string(addFromLiteralData(characters, length)) { } + template<unsigned charactersCount> ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], ConstructFromLiteralTag) : m_string(addFromLiteralData(characters, charactersCount - 1)) @@ -69,12 +77,10 @@ public: #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) // We have to declare the copy constructor and copy assignment operator as well, otherwise // they'll be implicitly deleted by adding the move constructor and move assignment operator. - // FIXME: Instead of explicitly casting to String&& here, we should use std::move, but that requires us to - // have a standard library that supports move semantics. AtomicString(const AtomicString& other) : m_string(other.m_string) { } - AtomicString(AtomicString&& other) : m_string(static_cast<String&&>(other.m_string)) { } + AtomicString(AtomicString&& other) : m_string(std::move(other.m_string)) { } AtomicString& operator=(const AtomicString& other) { m_string = other.m_string; return *this; } - AtomicString& operator=(AtomicString&& other) { m_string = static_cast<String&&>(other.m_string); return *this; } + AtomicString& operator=(AtomicString&& other) { m_string = std::move(other.m_string); return *this; } #endif // Hash table deleted values, which are only constructed and never copied or destroyed. @@ -102,10 +108,10 @@ public: bool contains(const String& s, bool caseSensitive = true) const { return m_string.contains(s, caseSensitive); } - size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); } - size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) const + size_t find(UChar c, unsigned start = 0) const { return m_string.find(c, start); } + size_t find(const LChar* s, unsigned start = 0, bool caseSentitive = true) const { return m_string.find(s, start, caseSentitive); } - size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const + size_t find(const String& s, unsigned start = 0, bool caseSentitive = true) const { return m_string.find(s, start, caseSentitive); } bool startsWith(const String& s, bool caseSensitive = true) const @@ -176,11 +182,13 @@ private: WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length); - ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r) + ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* string) { - if (!r || r->isAtomic()) - return r; - return addSlowCase(r); + if (!string || string->isAtomic()) { + ASSERT_WITH_MESSAGE(!string || isInAtomicStringTable(string), "The atomic string comes from an other thread!"); + return string; + } + return addSlowCase(string); } WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addFromLiteralData(const char* characters, unsigned length); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addSlowCase(StringImpl*); @@ -189,6 +197,10 @@ private: #endif WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, const char*); + +#if !ASSERT_DISABLED + WTF_EXPORT_STRING_API static bool isInAtomicStringTable(StringImpl*); +#endif }; inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); } diff --git a/Source/WTF/wtf/text/AtomicStringImpl.h b/Source/WTF/wtf/text/AtomicStringImpl.h index 0716275a8..8910cb2a1 100644 --- a/Source/WTF/wtf/text/AtomicStringImpl.h +++ b/Source/WTF/wtf/text/AtomicStringImpl.h @@ -31,6 +31,18 @@ public: AtomicStringImpl() : StringImpl(0) {} }; +#if !ASSERT_DISABLED +// AtomicStringImpls created from StaticASCIILiteral will ASSERT +// in the generic ValueCheck<T>::checkConsistency +// as they are not allocated by fastMalloc. +// We don't currently have any way to detect that case +// so we ignore the consistency check for all AtomicStringImpls*. +template<> struct +ValueCheck<AtomicStringImpl*> { + static void checkConsistency(const AtomicStringImpl*) { } +}; +#endif + } using WTF::AtomicStringImpl; diff --git a/Source/WTF/wtf/text/AtomicStringTable.cpp b/Source/WTF/wtf/text/AtomicStringTable.cpp new file mode 100644 index 000000000..d961b17e2 --- /dev/null +++ b/Source/WTF/wtf/text/AtomicStringTable.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "AtomicStringTable.h" + +#include <wtf/HashSet.h> +#include <wtf/MainThread.h> +#include <wtf/WTFThreadData.h> + +namespace WTF { + +void AtomicStringTable::create(WTFThreadData& data) +{ +#if USE(WEB_THREAD) + // On iOS, one AtomicStringTable is shared between the main UI thread and the WebThread. + static AtomicStringTable* sharedStringTable = new AtomicStringTable; + + bool currentThreadIsWebThread = isWebThread(); + if (currentThreadIsWebThread || isUIThread()) + data.m_atomicStringTable = sharedStringTable; + else + data.m_atomicStringTable = new AtomicStringTable; + + // We do the following so that its destruction happens only + // once - on the main UI thread. + if (!currentThreadIsWebThread) + data.m_atomicStringTableDestructor = AtomicStringTable::destroy; +#else + data.m_atomicStringTable = new AtomicStringTable; + data.m_atomicStringTableDestructor = AtomicStringTable::destroy; +#endif // USE(WEB_THREAD) +} + +void AtomicStringTable::destroy(AtomicStringTable* table) +{ + HashSet<StringImpl*>::iterator end = table->m_table.end(); + for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) + (*iter)->setIsAtomic(false); + delete table; +} + +} diff --git a/Source/WTF/wtf/text/AtomicStringTable.h b/Source/WTF/wtf/text/AtomicStringTable.h new file mode 100644 index 000000000..57826cb71 --- /dev/null +++ b/Source/WTF/wtf/text/AtomicStringTable.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_AtomicStringTable_h +#define WTF_AtomicStringTable_h + +#include <wtf/HashSet.h> +#include <wtf/WTFThreadData.h> + +namespace WTF { + +class StringImpl; + +class AtomicStringTable { + WTF_MAKE_FAST_ALLOCATED; +public: + + static void create(WTFThreadData&); + HashSet<StringImpl*>& table() { return m_table; } + +private: + static void destroy(AtomicStringTable*); + + HashSet<StringImpl*> m_table; +}; + +} + +#endif diff --git a/Source/WTF/wtf/text/CString.cpp b/Source/WTF/wtf/text/CString.cpp index fe1485532..ffddcac56 100644 --- a/Source/WTF/wtf/text/CString.cpp +++ b/Source/WTF/wtf/text/CString.cpp @@ -99,13 +99,27 @@ void CString::copyBufferIfNeeded() memcpy(m_buffer->mutableData(), buffer->data(), length + 1); } +bool CString::isSafeToSendToAnotherThread() const +{ + return !m_buffer || m_buffer->hasOneRef(); +} + bool operator==(const CString& a, const CString& b) { if (a.isNull() != b.isNull()) return false; if (a.length() != b.length()) return false; - return !strncmp(a.data(), b.data(), min(a.length(), b.length())); + return !memcmp(a.data(), b.data(), a.length()); +} + +bool operator==(const CString& a, const char* b) +{ + if (a.isNull() != !b) + return false; + if (!b) + return true; + return !strcmp(a.data(), b); } } // namespace WTF diff --git a/Source/WTF/wtf/text/CString.h b/Source/WTF/wtf/text/CString.h index 4d894b196..94f0a116a 100644 --- a/Source/WTF/wtf/text/CString.h +++ b/Source/WTF/wtf/text/CString.h @@ -72,6 +72,7 @@ public: } bool isNull() const { return !m_buffer; } + bool isSafeToSendToAnotherThread() const; CStringBuffer* buffer() const { return m_buffer.get(); } @@ -83,6 +84,8 @@ private: WTF_EXPORT_PRIVATE bool operator==(const CString& a, const CString& b); inline bool operator!=(const CString& a, const CString& b) { return !(a == b); } +WTF_EXPORT_PRIVATE bool operator==(const CString& a, const char* b); +inline bool operator!=(const CString& a, const char* b) { return !(a == b); } } // namespace WTF diff --git a/Source/WTF/wtf/text/StringBuffer.h b/Source/WTF/wtf/text/StringBuffer.h index 0f66113e5..73cde83cf 100644 --- a/Source/WTF/wtf/text/StringBuffer.h +++ b/Source/WTF/wtf/text/StringBuffer.h @@ -71,7 +71,7 @@ public: unsigned length() const { return m_length; } CharType* characters() { return m_data; } - CharType& operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } + CharType& operator[](unsigned i) { ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); return m_data[i]; } CharType* release() { CharType* data = m_data; m_data = 0; return data; } diff --git a/Source/WTF/wtf/text/StringBuilder.cpp b/Source/WTF/wtf/text/StringBuilder.cpp index a143d0a10..81e5d2783 100644 --- a/Source/WTF/wtf/text/StringBuilder.cpp +++ b/Source/WTF/wtf/text/StringBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,7 +32,11 @@ namespace WTF { -static const unsigned minimumCapacity = 16; +static size_t expandedCapacity(size_t capacity, size_t newLength) +{ + static const size_t minimumCapacity = 16; + return std::max(capacity, std::max(minimumCapacity, newLength * 2)); +} void StringBuilder::reifyString() const { @@ -224,10 +228,10 @@ CharType* StringBuilder::appendUninitializedSlow(unsigned requiredLength) // If the buffer is valid it must be at least as long as the current builder contents! ASSERT(m_buffer->length() >= m_length); - reallocateBuffer<CharType>(std::max(requiredLength, std::max(minimumCapacity, m_buffer->length() * 2))); + reallocateBuffer<CharType>(expandedCapacity(capacity(), requiredLength)); } else { ASSERT(m_string.length() == m_length); - allocateBuffer(m_length ? m_string.getCharacters<CharType>() : 0, std::max(requiredLength, std::max(minimumCapacity, m_length * 2))); + allocateBuffer(m_length ? m_string.getCharacters<CharType>() : 0, expandedCapacity(capacity(), requiredLength)); } CharType* result = getBufferCharacters<CharType>() + m_length; @@ -259,10 +263,10 @@ void StringBuilder::append(const UChar* characters, unsigned length) // If the buffer is valid it must be at least as long as the current builder contents! ASSERT(m_buffer->length() >= m_length); - allocateBufferUpConvert(m_buffer->characters8(), requiredLength); + allocateBufferUpConvert(m_buffer->characters8(), expandedCapacity(capacity(), requiredLength)); } else { ASSERT(m_string.length() == m_length); - allocateBufferUpConvert(m_string.isNull() ? 0 : m_string.characters8(), std::max(requiredLength, std::max(minimumCapacity, m_length * 2))); + allocateBufferUpConvert(m_string.isNull() ? 0 : m_string.characters8(), expandedCapacity(capacity(), requiredLength)); } memcpy(m_bufferCharacters16 + m_length, characters, static_cast<size_t>(length) * sizeof(UChar)); diff --git a/Source/WTF/wtf/text/StringBuilder.h b/Source/WTF/wtf/text/StringBuilder.h index e65f8f301..cf77d61d0 100644 --- a/Source/WTF/wtf/text/StringBuilder.h +++ b/Source/WTF/wtf/text/StringBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -141,6 +141,16 @@ public: append(static_cast<LChar>(c)); } + void append(UChar32 c) + { + if (U_IS_BMP(c)) { + append(static_cast<UChar>(c)); + return; + } + append(U16_LEAD(c)); + append(U16_TRAIL(c)); + } + template<unsigned charactersCount> ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount]) { append(characters, charactersCount - 1); } @@ -169,7 +179,7 @@ public: AtomicString toAtomicString() const { if (!m_length) - return AtomicString(); + return emptyAtom; // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large. if (canShrink()) { @@ -207,7 +217,7 @@ public: UChar operator[](unsigned i) const { - ASSERT(i < m_length); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); if (m_is8Bit) return characters8()[i]; return characters16()[i]; diff --git a/Source/WTF/wtf/text/StringConcatenate.h b/Source/WTF/wtf/text/StringConcatenate.h index 9b1ec5790..fd6a5b2bf 100644 --- a/Source/WTF/wtf/text/StringConcatenate.h +++ b/Source/WTF/wtf/text/StringConcatenate.h @@ -164,8 +164,7 @@ public: void writeTo(UChar* destination) { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; + StringImpl::copyChars(destination, m_buffer, m_length); } private: @@ -259,8 +258,35 @@ public: void writeTo(UChar* destination) { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; + StringImpl::copyChars(destination, m_buffer, m_length); + } + +private: + const LChar* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter<ASCIILiteral> { +public: + StringTypeAdapter<ASCIILiteral>(ASCIILiteral buffer) + : m_buffer(reinterpret_cast<const LChar*>(static_cast<const char*>(buffer))) + , m_length(strlen(buffer)) + { + } + + size_t length() { return m_length; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + memcpy(destination, m_buffer, static_cast<size_t>(m_length)); + } + + void writeTo(UChar* destination) + { + StringImpl::copyChars(destination, m_buffer, m_length); } private: diff --git a/Source/WTF/wtf/text/StringHash.h b/Source/WTF/wtf/text/StringHash.h index 1928716bd..e1a0c25ea 100644 --- a/Source/WTF/wtf/text/StringHash.h +++ b/Source/WTF/wtf/text/StringHash.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2012 Apple Inc. All rights reserved + * Copyright (C) 2006, 2007, 2008, 2012, 2013 Apple Inc. All rights reserved * Copyright (C) Research In Motion Limited 2009. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -43,29 +43,9 @@ namespace WTF { struct StringHash { static unsigned hash(StringImpl* key) { return key->hash(); } - static bool equal(const StringImpl* a, const StringImpl* b) + static inline bool equal(const StringImpl* a, const StringImpl* b) { - if (a == b) - return true; - if (!a || !b) - return false; - - unsigned aLength = a->length(); - unsigned bLength = b->length(); - if (aLength != bLength) - return false; - - if (a->is8Bit()) { - if (b->is8Bit()) - return WTF::equal(a->characters8(), b->characters8(), aLength); - - return WTF::equal(a->characters8(), b->characters16(), aLength); - } - - if (b->is8Bit()) - return WTF::equal(a->characters16(), b->characters8(), aLength); - - return WTF::equal(a->characters16(), b->characters16(), aLength); + return equalNonNull(a, b); } static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } @@ -112,27 +92,9 @@ namespace WTF { return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), length); } - static bool equal(const StringImpl* a, const StringImpl* b) + static inline bool equal(const StringImpl* a, const StringImpl* b) { - if (a == b) - return true; - if (!a || !b) - return false; - unsigned length = a->length(); - if (length != b->length()) - return false; - - if (a->is8Bit()) { - if (b->is8Bit()) - return equalIgnoringCase(a->characters8(), b->characters8(), length); - - return equalIgnoringCase(b->characters16(), a->characters8(), length); - } - - if (b->is8Bit()) - return equalIgnoringCase(a->characters16(), b->characters8(), length); - - return equalIgnoringCase(a->characters16(), b->characters16(), length); + return equalIgnoringCaseNonNull(a, b); } static unsigned hash(const RefPtr<StringImpl>& key) diff --git a/Source/WTF/wtf/text/StringImpl.cpp b/Source/WTF/wtf/text/StringImpl.cpp index 0c8da50ff..d1a3b56e8 100644 --- a/Source/WTF/wtf/text/StringImpl.cpp +++ b/Source/WTF/wtf/text/StringImpl.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller ( mueller@kde.org ) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) * * This library is free software; you can redistribute it and/or @@ -28,6 +28,7 @@ #include "AtomicString.h" #include "StringBuffer.h" #include "StringHash.h" +#include <wtf/ProcessID.h> #include <wtf/StdLibExtras.h> #include <wtf/WTFThreadData.h> #include <wtf/unicode/CharacterNames.h> @@ -81,7 +82,7 @@ void StringStats::removeString(StringImpl* string) void StringStats::printStats() { - dataLogF("String stats for process id %d:\n", getpid()); + dataLogF("String stats for process id %d:\n", getCurrentProcessID()); unsigned long long totalNumberCharacters = m_total8BitData + m_total16BitData; double percent8Bit = m_totalNumberStrings ? ((double)m_number8BitStrings * 100) / (double)m_totalNumberStrings : 0.0; @@ -114,12 +115,10 @@ StringImpl::~StringImpl() if (isAtomic()) AtomicString::remove(this); -#if USE(JSC) if (isIdentifier()) { if (!wtfThreadData().currentIdentifierTable()->remove(this)) CRASH(); } -#endif BufferOwnership ownership = bufferOwnership(); @@ -149,39 +148,42 @@ StringImpl::~StringImpl() m_substringBuffer->deref(); } +void StringImpl::destroy(StringImpl* stringImpl) +{ + stringImpl->~StringImpl(); + fastFree(stringImpl); +} + PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters, unsigned length) { + ASSERT_WITH_MESSAGE(length, "Use StringImpl::empty() to create an empty string"); ASSERT(charactersAreAllASCII<LChar>(reinterpret_cast<const LChar*>(characters), length)); - return adoptRef(new StringImpl(characters, length, ConstructFromLiteral)); + return adoptRef(new StringImpl(reinterpret_cast<const LChar*>(characters), length, ConstructWithoutCopying)); } PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters) { - size_t length = strlen(characters); - ASSERT(charactersAreAllASCII<LChar>(reinterpret_cast<const LChar*>(characters), length)); - return adoptRef(new StringImpl(characters, length, ConstructFromLiteral)); + return createFromLiteral(characters, strlen(characters)); } -PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data) +PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length) { - if (!length) { - data = 0; + if (!length) return empty(); - } - // Allocate a single buffer large enough to contain the StringImpl - // struct as well as the data which it contains. This removes one - // heap allocation from this call. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar))) - CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(LChar); - StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); + return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying)); +} - data = reinterpret_cast<LChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length, Force8BitConstructor)); +PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const LChar* characters, unsigned length) +{ + if (!length) + return empty(); + + return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying)); } -PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data) +template <typename CharType> +inline PassRefPtr<StringImpl> StringImpl::createUninitializedInternal(unsigned length, CharType*& data) { if (!length) { data = 0; @@ -189,20 +191,30 @@ PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& } // Allocate a single buffer large enough to contain the StringImpl - // struct as well as the data which it contains. This removes one + // struct as well as the data which it contains. This removes one // heap allocation from this call. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) + if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharType))) CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(UChar); + size_t size = sizeof(StringImpl) + length * sizeof(CharType); StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); - data = reinterpret_cast<UChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length)); + data = reinterpret_cast<CharType*>(string + 1); + return constructInternal<CharType>(string, length); } -PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, LChar*& data) +PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& data) { - ASSERT(originalString->is8Bit()); + return createUninitializedInternal(length, data); +} + +PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data) +{ + return createUninitializedInternal(length, data); +} + +template <typename CharType> +inline PassRefPtr<StringImpl> StringImpl::reallocateInternal(PassRefPtr<StringImpl> originalString, unsigned length, CharType*& data) +{ ASSERT(originalString->hasOneRef()); ASSERT(originalString->bufferOwnership() == BufferInternal); @@ -212,58 +224,48 @@ PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalStr } // Same as createUninitialized() except here we use fastRealloc. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar))) + if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharType))) CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(LChar); + size_t size = sizeof(StringImpl) + length * sizeof(CharType); originalString->~StringImpl(); StringImpl* string = static_cast<StringImpl*>(fastRealloc(originalString.leakRef(), size)); - data = reinterpret_cast<LChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length, Force8BitConstructor)); + data = reinterpret_cast<CharType*>(string + 1); + return constructInternal<CharType>(string, length); +} + +PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, LChar*& data) +{ + ASSERT(originalString->is8Bit()); + return reallocateInternal(originalString, length, data); } PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data) { ASSERT(!originalString->is8Bit()); - ASSERT(originalString->hasOneRef()); - ASSERT(originalString->bufferOwnership() == BufferInternal); - - if (!length) { - data = 0; - return empty(); - } - - // Same as createUninitialized() except here we use fastRealloc. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) - CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(UChar); - originalString->~StringImpl(); - StringImpl* string = static_cast<StringImpl*>(fastRealloc(originalString.leakRef(), size)); - - data = reinterpret_cast<UChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length)); + return reallocateInternal(originalString, length, data); } -PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) +template <typename CharType> +inline PassRefPtr<StringImpl> StringImpl::createInternal(const CharType* characters, unsigned length) { if (!characters || !length) return empty(); - UChar* data; + CharType* data; RefPtr<StringImpl> string = createUninitialized(length, data); - memcpy(data, characters, length * sizeof(UChar)); + memcpy(data, characters, length * sizeof(CharType)); return string.release(); } -PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length) +PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) { - if (!characters || !length) - return empty(); + return createInternal(characters, length); +} - LChar* data; - RefPtr<StringImpl> string = createUninitialized(length, data); - memcpy(data, characters, length * sizeof(LChar)); - return string.release(); +PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length) +{ + return createInternal(characters, length); } PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, unsigned length) @@ -283,6 +285,11 @@ PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, return string.release(); } +PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* string) +{ + return StringImpl::create8BitIfPossible(string, lengthOfNullTerminatedString(string)); +} + PassRefPtr<StringImpl> StringImpl::create(const LChar* string) { if (!string) @@ -308,8 +315,6 @@ const UChar* StringImpl::getData16SlowCase() const STRING_STATS_ADD_UPCONVERTED_STRING(m_length); unsigned len = length(); - if (hasTerminatingNullCharacter()) - ++len; m_copyData16 = static_cast<UChar*>(fastMalloc(len * sizeof(UChar))); @@ -384,67 +389,64 @@ PassRefPtr<StringImpl> StringImpl::lower() { // Note: This is a hot function in the Dromaeo benchmark, specifically the // no-op code path up through the first 'return' statement. - + // First scan the string for uppercase and non-ASCII characters: bool noUpper = true; - UChar ored = 0; if (is8Bit()) { - const LChar* end = m_data8 + m_length; - for (const LChar* chp = m_data8; chp != end; ++chp) { - if (UNLIKELY(isASCIIUpper(*chp))) - noUpper = false; - ored |= *chp; + unsigned failingIndex; + for (unsigned i = 0; i < m_length; ++i) { + LChar character = m_data8[i]; + if (UNLIKELY((character & ~0x7F) || isASCIIUpper(character))) { + failingIndex = i; + goto SlowPath8bitLower; + } } - // Nothing to do if the string is all ASCII with no uppercase. - if (noUpper && !(ored & ~0x7F)) - return this; - - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; + return this; +SlowPath8bitLower: LChar* data8; - RefPtr<StringImpl> newImpl = createUninitialized(length, data8); + RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8); - if (!(ored & ~0x7F)) { - for (int32_t i = 0; i < length; ++i) - data8[i] = toASCIILower(m_data8[i]); + for (unsigned i = 0; i < failingIndex; ++i) + data8[i] = m_data8[i]; - return newImpl.release(); + for (unsigned i = failingIndex; i < m_length; ++i) { + LChar character = m_data8[i]; + if (!(character & ~0x7F)) + data8[i] = toASCIILower(character); + else + data8[i] = static_cast<LChar>(Unicode::toLower(character)); } - // Do a slower implementation for cases that include non-ASCII Latin-1 characters. - for (int32_t i = 0; i < length; ++i) - data8[i] = static_cast<LChar>(Unicode::toLower(m_data8[i])); - return newImpl.release(); } + unsigned ored = 0; - const UChar *end = m_data16 + m_length; - for (const UChar* chp = m_data16; chp != end; ++chp) { - if (UNLIKELY(isASCIIUpper(*chp))) + for (unsigned i = 0; i < m_length; ++i) { + UChar character = m_data16[i]; + if (UNLIKELY(isASCIIUpper(character))) noUpper = false; - ored |= *chp; + ored |= character; } // Nothing to do if the string is all ASCII with no uppercase. if (noUpper && !(ored & ~0x7F)) return this; - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; - if (!(ored & ~0x7F)) { UChar* data16; RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); - for (int32_t i = 0; i < length; ++i) { + for (unsigned i = 0; i < m_length; ++i) { UChar c = m_data16[i]; data16[i] = toASCIILower(c); } return newImpl.release(); } - + + if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) + CRASH(); + int32_t length = m_length; + // Do a slower implementation for cases that include non-ASCII characters. UChar* data16; RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); @@ -476,7 +478,7 @@ PassRefPtr<StringImpl> StringImpl::upper() RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8); // Do a faster loop for the case where all the characters are ASCII. - LChar ored = 0; + unsigned ored = 0; for (int i = 0; i < length; ++i) { LChar c = m_data8[i]; ored |= c; @@ -537,7 +539,7 @@ upconvert: RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); // Do a faster loop for the case where all the characters are ASCII. - UChar ored = 0; + unsigned ored = 0; for (int i = 0; i < length; ++i) { UChar c = source16[i]; ored |= c; @@ -1121,6 +1123,13 @@ size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index) return findIgnoringCaseInner(characters16() + index, matchString->characters16(), index, searchLength, matchLength); } +size_t StringImpl::findNextLineStart(unsigned index) +{ + if (is8Bit()) + return WTF::findNextLineStart(characters8(), m_length, index); + return WTF::findNextLineStart(characters16(), m_length, index); +} + size_t StringImpl::reverseFind(UChar c, unsigned index) { if (is8Bit()) @@ -1245,6 +1254,24 @@ ALWAYS_INLINE static bool equalInner(const StringImpl* stringImpl, unsigned star return equalIgnoringCase(stringImpl->characters16() + startOffset, reinterpret_cast<const LChar*>(matchString), matchLength); } +bool StringImpl::startsWith(const StringImpl* str) const +{ + if (!str) + return false; + + if (str->length() > length()) + return false; + + if (is8Bit()) { + if (str->is8Bit()) + return equal(characters8(), str->characters8(), str->length()); + return equal(characters8(), str->characters16(), str->length()); + } + if (str->is8Bit()) + return equal(characters16(), str->characters8(), str->length()); + return equal(characters16(), str->characters16(), str->length()); +} + bool StringImpl::startsWith(UChar character) const { return m_length && (*this)[0] == character; @@ -1665,26 +1692,61 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl return newImpl.release(); } +static inline bool stringImplContentEqual(const StringImpl* a, const StringImpl* b) +{ + unsigned aLength = a->length(); + unsigned bLength = b->length(); + if (aLength != bLength) + return false; + + if (a->is8Bit()) { + if (b->is8Bit()) + return equal(a->characters8(), b->characters8(), aLength); + + return equal(a->characters8(), b->characters16(), aLength); + } + + if (b->is8Bit()) + return equal(a->characters16(), b->characters8(), aLength); + + return equal(a->characters16(), b->characters16(), aLength); +} + bool equal(const StringImpl* a, const StringImpl* b) { - return StringHash::equal(a, b); + if (a == b) + return true; + if (!a || !b) + return false; + + return stringImplContentEqual(a, b); } -bool equal(const StringImpl* a, const LChar* b, unsigned length) +template <typename CharType> +inline bool equalInternal(const StringImpl* a, const CharType* b, unsigned length) { if (!a) return !b; if (!b) - return !a; - - if (length != a->length()) return false; + if (a->length() != length) + return false; if (a->is8Bit()) return equal(a->characters8(), b, length); return equal(a->characters16(), b, length); } +bool equal(const StringImpl* a, const LChar* b, unsigned length) +{ + return equalInternal(a, b, length); +} + +bool equal(const StringImpl* a, const UChar* b, unsigned length) +{ + return equalInternal(a, b, length); +} + bool equal(const StringImpl* a, const LChar* b) { if (!a) @@ -1720,26 +1782,26 @@ bool equal(const StringImpl* a, const LChar* b) return !b[length]; } -bool equal(const StringImpl* a, const UChar* b, unsigned length) +bool equalNonNull(const StringImpl* a, const StringImpl* b) { - if (!a) - return !b; - if (!b) - return false; + ASSERT(a && b); + if (a == b) + return true; - if (a->length() != length) - return false; - if (a->is8Bit()) - return equal(a->characters8(), b, length); - return equal(a->characters16(), b, length); + return stringImplContentEqual(a, b); } -bool equalIgnoringCase(StringImpl* a, StringImpl* b) +bool equalIgnoringCase(const StringImpl* a, const StringImpl* b) { + if (a == b) + return true; + if (!a || !b) + return false; + return CaseFoldingHash::equal(a, b); } -bool equalIgnoringCase(StringImpl* a, const LChar* b) +bool equalIgnoringCase(const StringImpl* a, const LChar* b) { if (!a) return !b; @@ -1793,16 +1855,36 @@ bool equalIgnoringCase(StringImpl* a, const LChar* b) return equal && !b[length]; } -bool equalIgnoringNullity(StringImpl* a, StringImpl* b) +bool equalIgnoringCaseNonNull(const StringImpl* a, const StringImpl* b) { - if (StringHash::equal(a, b)) + ASSERT(a && b); + if (a == b) return true; + + unsigned length = a->length(); + if (length != b->length()) + return false; + + if (a->is8Bit()) { + if (b->is8Bit()) + return equalIgnoringCase(a->characters8(), b->characters8(), length); + + return equalIgnoringCase(b->characters16(), a->characters8(), length); + } + + if (b->is8Bit()) + return equalIgnoringCase(a->characters16(), b->characters8(), length); + + return equalIgnoringCase(a->characters16(), b->characters16(), length); +} + +bool equalIgnoringNullity(StringImpl* a, StringImpl* b) +{ if (!a && b && !b->length()) return true; if (!b && a && !a->length()) return true; - - return false; + return equal(a, b); } WTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality) @@ -1853,30 +1935,6 @@ PassRefPtr<StringImpl> StringImpl::adopt(QStringData* qStringData) } #endif -PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string) -{ - // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer - // get allocated in a single memory block. - unsigned length = string.m_length; - if (length >= numeric_limits<unsigned>::max()) - CRASH(); - RefPtr<StringImpl> terminatedString; - if (string.is8Bit()) { - LChar* data; - terminatedString = createUninitialized(length + 1, data); - memcpy(data, string.m_data8, length * sizeof(LChar)); - data[length] = 0; - } else { - UChar* data; - terminatedString = createUninitialized(length + 1, data); - memcpy(data, string.m_data16, length * sizeof(UChar)); - data[length] = 0; - } - --(terminatedString->m_length); - terminatedString->m_hashAndFlags = (string.m_hashAndFlags & (~s_flagMask | s_hashFlag8BitBuffer)) | s_hashFlagHasTerminatingNullCharacter; - return terminatedString.release(); -} - size_t StringImpl::sizeInBytes() const { // FIXME: support substrings @@ -1884,8 +1942,6 @@ size_t StringImpl::sizeInBytes() const if (is8Bit()) { if (has16BitShadow()) { size += 2 * size; - if (hasTerminatingNullCharacter()) - size += 2; } } else size *= 2; diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h index 2861949e5..0d6c358a4 100644 --- a/Source/WTF/wtf/text/StringImpl.h +++ b/Source/WTF/wtf/text/StringImpl.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. * Copyright (C) 2009 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -64,12 +64,14 @@ template<typename CharacterType> struct HashAndCharactersTranslator; struct HashAndUTF8CharactersTranslator; struct LCharBufferTranslator; struct CharBufferFromLiteralDataTranslator; -class MemoryObjectInfo; struct SubstringTranslator; struct UCharBufferTranslator; template<typename> class RetainPtr; -enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; +enum TextCaseSensitivity { + TextCaseSensitive, + TextCaseInsensitive +}; typedef bool (*CharacterMatchFunctionPtr)(UChar); typedef bool (*IsWhiteSpaceFunctionPtr)(UChar); @@ -240,17 +242,29 @@ private: STRING_STATS_ADD_8BIT_STRING(m_length); } - enum ConstructFromLiteralTag { ConstructFromLiteral }; - StringImpl(const char* characters, unsigned length, ConstructFromLiteralTag) + enum ConstructWithoutCopyingTag { ConstructWithoutCopying }; + StringImpl(const UChar* characters, unsigned length, ConstructWithoutCopyingTag) : m_refCount(s_refCountIncrement) , m_length(length) - , m_data8(reinterpret_cast<const LChar*>(characters)) + , m_data16(characters) + , m_buffer(0) + , m_hashAndFlags(BufferInternal) + { + ASSERT(m_data16); + ASSERT(m_length); + + STRING_STATS_ADD_16BIT_STRING(0); + } + + StringImpl(const LChar* characters, unsigned length, ConstructWithoutCopyingTag) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data8(characters) , m_buffer(0) - , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal | s_hashFlagHasTerminatingNullCharacter) + , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) { ASSERT(m_data8); ASSERT(m_length); - ASSERT(!characters[length]); STRING_STATS_ADD_8BIT_STRING(0); } @@ -314,7 +328,7 @@ private: // keys means that we don't need them to match any other string (in fact, // that's exactly the oposite of what we want!), and teh normal hash would // lead to lots of conflicts. - unsigned hash = reinterpret_cast<uintptr_t>(this); + unsigned hash = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this)); hash <<= s_flagCount; if (!hash) hash = 1 << s_flagCount; @@ -347,13 +361,21 @@ private: STRING_STATS_ADD_16BIT_STRING(m_length); } #endif + ~StringImpl(); public: - WTF_EXPORT_STRING_API ~StringImpl(); + WTF_EXPORT_STRING_API static void destroy(StringImpl*); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> create(const UChar*, unsigned length); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> create(const LChar*, unsigned length); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned length); + template<size_t inlineCapacity> + static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlineCapacity>& vector) + { + return create8BitIfPossible(vector.data(), vector.size()); + } + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*); + ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned length) { return create(reinterpret_cast<const LChar*>(s), length); } WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> create(const LChar*); ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s) { return create(reinterpret_cast<const LChar*>(s)); } @@ -385,17 +407,22 @@ public: return adoptRef(new StringImpl(rep->m_data16 + offset, length, ownerRep)); } - WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters, unsigned length); template<unsigned charactersCount> ALWAYS_INLINE static PassRefPtr<StringImpl> createFromLiteral(const char (&characters)[charactersCount]) { COMPILE_ASSERT(charactersCount > 1, StringImplFromLiteralNotEmpty); COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), StringImplFromLiteralCannotOverflow); - return createFromLiteral(characters, charactersCount - 1); + return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1); } + + // FIXME: Transition off of these functions to createWithoutCopying instead. + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters, unsigned length); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters); + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const UChar* characters, unsigned length); + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const LChar* characters, unsigned length); + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data); template <typename T> static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, T*& output) @@ -416,10 +443,7 @@ public: } output = reinterpret_cast<T*>(resultImpl + 1); - if (sizeof(T) == sizeof(char)) - return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8BitConstructor)); - - return adoptRef(new (NotNull, resultImpl) StringImpl(length)); + return constructInternal<T>(resultImpl, length); } static PassRefPtr<StringImpl> createEmptyUnique() @@ -436,10 +460,9 @@ public: static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); } static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; } static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); } - static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); - template<typename CharType, size_t inlineCapacity> - static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity>& vector) + template<typename CharType, size_t inlineCapacity, typename OverflowHandler> + static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity, OverflowHandler>& vector) { if (size_t size = vector.size()) { ASSERT(vector.data()); @@ -459,9 +482,6 @@ public: unsigned length() const { return m_length; } bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } - bool hasInternalBuffer() const { return bufferOwnership() == BufferInternal; } - bool hasOwnedBuffer() const { return bufferOwnership() == BufferOwned; } - StringImpl* baseString() const { return bufferOwnership() == BufferSubstring ? m_substringBuffer : 0; } // FIXME: Remove all unnecessary usages of characters() ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_data8; } @@ -477,7 +497,7 @@ public: template <typename CharType> ALWAYS_INLINE const CharType * getCharacters() const; - size_t cost() + size_t cost() const { // For substrings, return the cost of the base string. if (bufferOwnership() == BufferSubstring) @@ -509,13 +529,11 @@ public: return !length() && !isStatic(); } - bool hasTerminatingNullCharacter() const { return m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter; } - bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } - void setIsAtomic(bool isIdentifier) + void setIsAtomic(bool isAtomic) { ASSERT(!isStatic()); - if (isIdentifier) + if (isAtomic) m_hashAndFlags |= s_hashFlagIsAtomic; else m_hashAndFlags &= ~s_hashFlagIsAtomic; @@ -583,12 +601,12 @@ public: inline void deref() { - if (m_refCount == s_refCountIncrement) { - delete this; + unsigned tempRefCount = m_refCount - s_refCountIncrement; + if (!tempRefCount) { + StringImpl::destroy(this); return; } - - m_refCount -= s_refCountIncrement; + m_refCount = tempRefCount; } WTF_EXPORT_PRIVATE static StringImpl* empty(); @@ -636,7 +654,7 @@ public: UChar operator[](unsigned i) const { - ASSERT(i < m_length); + ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); if (is8Bit()) return m_data8[i]; return m_data16[i]; @@ -684,22 +702,25 @@ public: size_t find(UChar character, unsigned start = 0); WTF_EXPORT_STRING_API size_t find(CharacterMatchFunctionPtr, unsigned index = 0); size_t find(const LChar*, unsigned index = 0); - ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); }; + ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); } WTF_EXPORT_STRING_API size_t find(StringImpl*); WTF_EXPORT_STRING_API size_t find(StringImpl*, unsigned index); size_t findIgnoringCase(const LChar*, unsigned index = 0); - ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); }; + ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); } WTF_EXPORT_STRING_API size_t findIgnoringCase(StringImpl*, unsigned index = 0); + WTF_EXPORT_STRING_API size_t findNextLineStart(unsigned index = UINT_MAX); + WTF_EXPORT_STRING_API size_t reverseFind(UChar, unsigned index = UINT_MAX); WTF_EXPORT_STRING_API size_t reverseFind(StringImpl*, unsigned index = UINT_MAX); WTF_EXPORT_STRING_API size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX); - bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; } + WTF_EXPORT_STRING_API bool startsWith(const StringImpl*) const; + bool startsWith(StringImpl* str, bool caseSensitive) { return caseSensitive ? startsWith(str) : (reverseFindIgnoringCase(str, 0) == 0); } WTF_EXPORT_STRING_API bool startsWith(UChar) const; WTF_EXPORT_STRING_API bool startsWith(const char*, unsigned matchLength, bool caseSensitive) const; template<unsigned matchLength> - bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const { return startsWith(prefix, matchLength - 1, caseSensitive); }; + bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const { return startsWith(prefix, matchLength - 1, caseSensitive); } WTF_EXPORT_STRING_API bool endsWith(StringImpl*, bool caseSensitive = true); WTF_EXPORT_STRING_API bool endsWith(UChar) const; @@ -729,6 +750,16 @@ public: #endif private: + bool requiresCopy() const + { + if (bufferOwnership() != BufferInternal) + return true; + + if (is8Bit()) + return reinterpret_cast<const void*>(m_data8) == reinterpret_cast<const void*>(this + 1); + return reinterpret_cast<const void*>(m_data16) == reinterpret_cast<const void*>(this + 1); + } + // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. static const unsigned s_copyCharsInlineCutOff = 20; @@ -736,6 +767,10 @@ private: bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacters(UCharPredicate); template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> simplifyMatchedCharactersToSpace(UCharPredicate); + template <typename CharType> static PassRefPtr<StringImpl> constructInternal(StringImpl*, unsigned); + template <typename CharType> static PassRefPtr<StringImpl> createUninitializedInternal(unsigned, CharType*&); + template <typename CharType> static PassRefPtr<StringImpl> reallocateInternal(PassRefPtr<StringImpl>, unsigned, CharType*&); + template <typename CharType> static PassRefPtr<StringImpl> createInternal(const CharType*, unsigned); WTF_EXPORT_STRING_API NEVER_INLINE const UChar* getData16SlowCase() const; WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const; @@ -743,14 +778,13 @@ private: static const unsigned s_refCountFlagIsStaticString = 0x1; static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag. - // The bottom 8 bits in the hash are flags. - static const unsigned s_flagCount = 8; + // The bottom 7 bits in the hash are flags. + static const unsigned s_flagCount = 7; static const unsigned s_flagMask = (1u << s_flagCount) - 1; - COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); + COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); - static const unsigned s_hashFlagHas16BitShadow = 1u << 7; - static const unsigned s_hashFlag8BitBuffer = 1u << 6; - static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5; + static const unsigned s_hashFlagHas16BitShadow = 1u << 6; + static const unsigned s_hashFlag8BitBuffer = 1u << 5; static const unsigned s_hashFlagIsAtomic = 1u << 4; static const unsigned s_hashFlagDidReportCost = 1u << 3; static const unsigned s_hashFlagIsIdentifier = 1u << 2; @@ -759,6 +793,32 @@ private: #ifdef STRING_STATS WTF_EXPORTDATA static StringStats m_stringStats; #endif + +public: + struct StaticASCIILiteral { + // These member variables must match the layout of StringImpl. + unsigned m_refCount; + unsigned m_length; + const LChar* m_data8; + void* m_buffer; + unsigned m_hashAndFlags; + + // These values mimic ConstructFromLiteral. + static const unsigned s_initialRefCount = s_refCountIncrement; + static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInternal; + static const unsigned s_hashShift = s_flagCount; + }; + +#ifndef NDEBUG + void assertHashIsCorrect() + { + ASSERT(hasHash()); + ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(characters8(), length())); + } +#endif + +private: + // These member variables must match the layout of StaticASCIILiteral. unsigned m_refCount; unsigned m_length; union { @@ -776,6 +836,25 @@ private: mutable unsigned m_hashAndFlags; }; +COMPILE_ASSERT(sizeof(StringImpl) == sizeof(StringImpl::StaticASCIILiteral), StringImpl_should_match_its_StaticASCIILiteral); + +#if !ASSERT_DISABLED +// StringImpls created from StaticASCIILiteral will ASSERT +// in the generic ValueCheck<T>::checkConsistency +// as they are not allocated by fastMalloc. +// We don't currently have any way to detect that case +// so we ignore the consistency check for all StringImpl*. +template<> struct +ValueCheck<StringImpl*> { + static void checkConsistency(const StringImpl*) { } +}; +#endif + +template <> +ALWAYS_INLINE PassRefPtr<StringImpl> StringImpl::constructInternal<LChar>(StringImpl* impl, unsigned length) { return adoptRef(new (NotNull, impl) StringImpl(length, Force8BitConstructor)); } +template <> +ALWAYS_INLINE PassRefPtr<StringImpl> StringImpl::constructInternal<UChar>(StringImpl* impl, unsigned length) { return adoptRef(new (NotNull, impl) StringImpl(length)); } + template <> ALWAYS_INLINE const LChar* StringImpl::getCharacters<LChar>() const { return characters8(); } @@ -786,10 +865,11 @@ WTF_EXPORT_STRING_API bool equal(const StringImpl*, const StringImpl*); WTF_EXPORT_STRING_API bool equal(const StringImpl*, const LChar*); inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast<const LChar*>(b)); } WTF_EXPORT_STRING_API bool equal(const StringImpl*, const LChar*, unsigned); +WTF_EXPORT_STRING_API bool equal(const StringImpl*, const UChar*, unsigned); inline bool equal(const StringImpl* a, const char* b, unsigned length) { return equal(a, reinterpret_cast<const LChar*>(b), length); } inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); } inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); } -WTF_EXPORT_STRING_API bool equal(const StringImpl*, const UChar*, unsigned); +WTF_EXPORT_STRING_API bool equalNonNull(const StringImpl* a, const StringImpl* b); // Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe. #if CPU(X86_64) @@ -905,51 +985,113 @@ ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) return true; } -#else +#elif PLATFORM(IOS) && WTF_ARM_ARCH_AT_LEAST(7) ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) { - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; + bool isEqual = false; + uint32_t aValue; + uint32_t bValue; + asm("subs %[length], #4\n" + "blo 2f\n" + + "0:\n" // Label 0 = Start of loop over 32 bits. + "ldr %[aValue], [%[a]], #4\n" + "ldr %[bValue], [%[b]], #4\n" + "cmp %[aValue], %[bValue]\n" + "bne 66f\n" + "subs %[length], #4\n" + "bhs 0b\n" + + // At this point, length can be: + // -0: 00000000000000000000000000000000 (0 bytes left) + // -1: 11111111111111111111111111111111 (3 bytes left) + // -2: 11111111111111111111111111111110 (2 bytes left) + // -3: 11111111111111111111111111111101 (1 byte left) + // -4: 11111111111111111111111111111100 (length was 0) + // The pointers are at the correct position. + "2:\n" // Label 2 = End of loop over 32 bits, check for pair of characters. + "tst %[length], #2\n" + "beq 1f\n" + "ldrh %[aValue], [%[a]], #2\n" + "ldrh %[bValue], [%[b]], #2\n" + "cmp %[aValue], %[bValue]\n" + "bne 66f\n" + + "1:\n" // Label 1 = Check for a single character left. + "tst %[length], #1\n" + "beq 42f\n" + "ldrb %[aValue], [%[a]]\n" + "ldrb %[bValue], [%[b]]\n" + "cmp %[aValue], %[bValue]\n" + "bne 66f\n" + + "42:\n" // Label 42 = Success. + "mov %[isEqual], #1\n" + "66:\n" // Label 66 = End without changing isEqual to 1. + : [length]"+r"(length), [isEqual]"+r"(isEqual), [a]"+r"(a), [b]"+r"(b), [aValue]"+r"(aValue), [bValue]"+r"(bValue) + : + : + ); + return isEqual; } ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) { - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; + bool isEqual = false; + uint32_t aValue; + uint32_t bValue; + asm("subs %[length], #2\n" + "blo 1f\n" + + "0:\n" // Label 0 = Start of loop over 32 bits. + "ldr %[aValue], [%[a]], #4\n" + "ldr %[bValue], [%[b]], #4\n" + "cmp %[aValue], %[bValue]\n" + "bne 66f\n" + "subs %[length], #2\n" + "bhs 0b\n" + + // At this point, length can be: + // -0: 00000000000000000000000000000000 (0 bytes left) + // -1: 11111111111111111111111111111111 (1 character left, 2 bytes) + // -2: 11111111111111111111111111111110 (length was zero) + // The pointers are at the correct position. + "1:\n" // Label 1 = Check for a single character left. + "tst %[length], #1\n" + "beq 42f\n" + "ldrh %[aValue], [%[a]]\n" + "ldrh %[bValue], [%[b]]\n" + "cmp %[aValue], %[bValue]\n" + "bne 66f\n" + + "42:\n" // Label 42 = Success. + "mov %[isEqual], #1\n" + "66:\n" // Label 66 = End without changing isEqual to 1. + : [length]"+r"(length), [isEqual]"+r"(isEqual), [a]"+r"(a), [b]"+r"(b), [aValue]"+r"(aValue), [bValue]"+r"(bValue) + : + : + ); + return isEqual; } +#else +ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) { return !memcmp(a, b, length); } +ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) { return !memcmp(a, b, length * sizeof(UChar)); } #endif ALWAYS_INLINE bool equal(const LChar* a, const UChar* b, unsigned length) { - for (unsigned i = 0; i != length; ++i) { + for (unsigned i = 0; i < length; ++i) { if (a[i] != b[i]) return false; } - return true; } -ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length) -{ - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; -} +ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length) { return equal(b, a, length); } -WTF_EXPORT_STRING_API bool equalIgnoringCase(StringImpl*, StringImpl*); -WTF_EXPORT_STRING_API bool equalIgnoringCase(StringImpl*, const LChar*); -inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); } +WTF_EXPORT_STRING_API bool equalIgnoringCase(const StringImpl*, const StringImpl*); +WTF_EXPORT_STRING_API bool equalIgnoringCase(const StringImpl*, const LChar*); +inline bool equalIgnoringCase(const LChar* a, const StringImpl* b) { return equalIgnoringCase(b, a); } WTF_EXPORT_STRING_API bool equalIgnoringCase(const LChar*, const LChar*, unsigned); WTF_EXPORT_STRING_API bool equalIgnoringCase(const UChar*, const LChar*, unsigned); inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast<const LChar*>(b), length); } @@ -961,6 +1103,7 @@ inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length) ASSERT(length >= 0); return !Unicode::umemcasecmp(a, b, length); } +WTF_EXPORT_STRING_API bool equalIgnoringCaseNonNull(const StringImpl*, const StringImpl*); WTF_EXPORT_STRING_API bool equalIgnoringNullity(StringImpl*, StringImpl*); @@ -1007,7 +1150,54 @@ inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunct return notFound; } -template <typename CharacterType> +template<typename CharacterType> +inline size_t findNextLineStart(const CharacterType* characters, unsigned length, unsigned index = 0) +{ + while (index < length) { + CharacterType c = characters[index++]; + if ((c != '\n') && (c != '\r')) + continue; + + // There can only be a start of a new line if there are more characters + // beyond the current character. + if (index < length) { + // The 3 common types of line terminators are 1. \r\n (Windows), + // 2. \r (old MacOS) and 3. \n (Unix'es). + + if (c == '\n') + return index; // Case 3: just \n. + + CharacterType c2 = characters[index]; + if (c2 != '\n') + return index; // Case 2: just \r. + + // Case 1: \r\n. + // But, there's only a start of a new line if there are more + // characters beyond the \r\n. + if (++index < length) + return index; + } + } + return notFound; +} + +template<typename CharacterType> +inline size_t reverseFindLineTerminator(const CharacterType* characters, unsigned length, unsigned index = UINT_MAX) +{ + if (!length) + return notFound; + if (index >= length) + index = length - 1; + CharacterType c = characters[index]; + while ((c != '\n') && (c != '\r')) { + if (!index--) + return notFound; + c = characters[index]; + } + return index; +} + +template<typename CharacterType> inline size_t reverseFind(const CharacterType* characters, unsigned length, CharacterType matchCharacter, unsigned index = UINT_MAX) { if (!length) @@ -1124,8 +1314,26 @@ static inline bool isSpaceOrNewline(UChar c) return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF::Unicode::WhiteSpaceNeutral; } +template<typename CharacterType> +inline unsigned lengthOfNullTerminatedString(const CharacterType* string) +{ + ASSERT(string); + size_t length = 0; + while (string[length]) + ++length; + + RELEASE_ASSERT(length < std::numeric_limits<unsigned>::max()); + return static_cast<unsigned>(length); +} + inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const { + if (!requiresCopy()) { + if (is8Bit()) + return StringImpl::createWithoutCopying(m_data8, m_length); + return StringImpl::createWithoutCopying(m_data16, m_length); + } + if (is8Bit()) return create(m_data8, m_length); return create(m_data16, m_length); @@ -1146,6 +1354,7 @@ template<> struct DefaultHash<RefPtr<StringImpl> > { using WTF::StringImpl; using WTF::equal; +using WTF::equalNonNull; using WTF::TextCaseSensitivity; using WTF::TextCaseSensitive; using WTF::TextCaseInsensitive; diff --git a/Source/WTF/wtf/text/StringOperators.h b/Source/WTF/wtf/text/StringOperators.h index 9e1637be1..843e173ac 100644 --- a/Source/WTF/wtf/text/StringOperators.h +++ b/Source/WTF/wtf/text/StringOperators.h @@ -112,7 +112,7 @@ inline StringAppend<const char*, AtomicString> operator+(const char* string1, co } template<typename U, typename V> -StringAppend<const char*, StringAppend<U, V> > operator+(const char* string1, const StringAppend<U, V>& string2) +inline StringAppend<const char*, StringAppend<U, V> > operator+(const char* string1, const StringAppend<U, V>& string2) { return StringAppend<const char*, StringAppend<U, V> >(string1, string2); } @@ -128,11 +128,27 @@ inline StringAppend<const UChar*, AtomicString> operator+(const UChar* string1, } template<typename U, typename V> -StringAppend<const UChar*, StringAppend<U, V> > operator+(const UChar* string1, const StringAppend<U, V>& string2) +inline StringAppend<const UChar*, StringAppend<U, V> > operator+(const UChar* string1, const StringAppend<U, V>& string2) { return StringAppend<const UChar*, StringAppend<U, V> >(string1, string2); } +inline StringAppend<ASCIILiteral, String> operator+(const ASCIILiteral& string1, const String& string2) +{ + return StringAppend<ASCIILiteral, String>(string1, string2); +} + +inline StringAppend<ASCIILiteral, AtomicString> operator+(const ASCIILiteral& string1, const AtomicString& string2) +{ + return StringAppend<ASCIILiteral, AtomicString>(string1, string2); +} + +template<typename U, typename V> +inline StringAppend<ASCIILiteral, StringAppend<U, V> > operator+(const ASCIILiteral& string1, const StringAppend<U, V>& string2) +{ + return StringAppend<ASCIILiteral, StringAppend<U, V> >(string1, string2); +} + template<typename T> StringAppend<String, T> operator+(const String& string1, T string2) { diff --git a/Source/WTF/wtf/text/WTFString.cpp b/Source/WTF/wtf/text/WTFString.cpp index 5038bf924..29c13c10d 100644 --- a/Source/WTF/wtf/text/WTFString.cpp +++ b/Source/WTF/wtf/text/WTFString.cpp @@ -28,6 +28,7 @@ #include <wtf/DataLog.h> #include <wtf/HexNumber.h> #include <wtf/MathExtras.h> +#include <wtf/NeverDestroyed.h> #include <wtf/text/CString.h> #include <wtf/StringExtras.h> #include <wtf/Vector.h> @@ -54,15 +55,8 @@ String::String(const UChar* str) { if (!str) return; - - size_t len = 0; - while (str[len] != UChar(0)) - ++len; - if (len > numeric_limits<unsigned>::max()) - CRASH(); - - m_impl = StringImpl::create(str, len); + m_impl = StringImpl::create(str, lengthOfNullTerminatedString(str)); } // Construct a string with latin1 data. @@ -125,7 +119,8 @@ void String::append(const String& str) } } -void String::append(LChar c) +template <typename CharacterType> +inline void String::appendInternal(CharacterType c) { // FIXME: This is extremely inefficient. So much so that we might want to take this // out of String's API. We can make it better by optimizing the case where exactly @@ -143,22 +138,14 @@ void String::append(LChar c) m_impl = StringImpl::create(&c, 1); } +void String::append(LChar c) +{ + appendInternal(c); +} + void String::append(UChar c) { - // FIXME: This is extremely inefficient. So much so that we might want to take this - // out of String's API. We can make it better by optimizing the case where exactly - // one String is pointing at this StringImpl, but even then it's going to require a - // call to fastMalloc every single time. - if (m_impl) { - UChar* data; - if (m_impl->length() >= numeric_limits<unsigned>::max()) - CRASH(); - RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length() + 1, data); - memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); - data[m_impl->length()] = c; - m_impl = newImpl.release(); - } else - m_impl = StringImpl::create(&c, 1); + appendInternal(c); } int codePointCompare(const String& a, const String& b) @@ -400,14 +387,26 @@ bool String::percentage(int& result) const return true; } -const UChar* String::charactersWithNullTermination() +Vector<UChar> String::charactersWithNullTermination() const { - if (!m_impl) - return 0; - if (m_impl->hasTerminatingNullCharacter()) - return m_impl->characters(); - m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl); - return m_impl->characters(); + Vector<UChar> result; + + if (m_impl) { + result.reserveInitialCapacity(length() + 1); + + if (is8Bit()) { + const LChar* characters8 = m_impl->characters8(); + for (size_t i = 0; i < length(); ++i) + result.uncheckedAppend(characters8[i]); + } else { + const UChar* characters16 = m_impl->characters16(); + result.append(characters16, m_impl->length()); + } + + result.append(0); + } + + return result; } String String::format(const char *format, ...) @@ -654,12 +653,50 @@ float String::toFloat(bool* ok) const return m_impl->toFloat(ok); } +#if COMPILER_SUPPORTS(CXX_REFERENCE_QUALIFIED_FUNCTIONS) +String String::isolatedCopy() const & +{ + if (!m_impl) + return String(); + return m_impl->isolatedCopy(); +} + +String String::isolatedCopy() const && +{ + if (isSafeToSendToAnotherThread()) { + // Since we know that our string is a temporary that will be destroyed + // we can just steal the m_impl from it, thus avoiding a copy. + return String(std::move(*this)); + } + + if (!m_impl) + return String(); + + return m_impl->isolatedCopy(); +} +#else String String::isolatedCopy() const { if (!m_impl) return String(); return m_impl->isolatedCopy(); } +#endif + +bool String::isSafeToSendToAnotherThread() const +{ + if (!impl()) + return true; + // AtomicStrings are not safe to send between threads as ~StringImpl() + // will try to remove them from the wrong AtomicStringTable. + if (impl()->isAtomic()) + return false; + if (impl()->hasOneRef()) + return true; + if (isEmpty()) + return true; + return false; +} void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const { @@ -880,29 +917,20 @@ String String::fromUTF8(const LChar* stringStart, size_t length) if (!length) return emptyString(); - // We'll use a StringImpl as a buffer; if the source string only contains ascii this should be - // the right length, if there are any multi-byte sequences this buffer will be too large. - UChar* buffer; - String stringBuffer(StringImpl::createUninitialized(length, buffer)); - UChar* bufferEnd = buffer + length; + if (charactersAreAllASCII(stringStart, length)) + return StringImpl::create(stringStart, length); + + Vector<UChar, 1024> buffer(length); + UChar* bufferStart = buffer.data(); - // Try converting into the buffer. + UChar* bufferCurrent = bufferStart; const char* stringCurrent = reinterpret_cast<const char*>(stringStart); - bool isAllASCII; - if (convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + length), &buffer, bufferEnd, &isAllASCII) != conversionOK) + if (convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + length), &bufferCurrent, bufferCurrent + buffer.size()) != conversionOK) return String(); - if (isAllASCII) - return String(stringStart, length); - - // stringBuffer is full (the input must have been all ascii) so just return it! - if (buffer == bufferEnd) - return stringBuffer; - - // stringBuffer served its purpose as a buffer, copy the contents out into a new string. - unsigned utf16Length = buffer - stringBuffer.characters(); + unsigned utf16Length = bufferCurrent - bufferStart; ASSERT(utf16Length < length); - return String(stringBuffer.characters(), utf16Length); + return StringImpl::create(bufferStart, utf16Length); } String String::fromUTF8(const LChar* string) @@ -912,6 +940,11 @@ String String::fromUTF8(const LChar* string) return fromUTF8(string, strlen(reinterpret_cast<const char*>(string))); } +String String::fromUTF8(const CString& s) +{ + return fromUTF8(s.data()); +} + String String::fromUTF8WithLatin1Fallback(const LChar* string, size_t size) { String utf8 = fromUTF8(string, size); @@ -1199,7 +1232,8 @@ float charactersToFloat(const UChar* data, size_t length, size_t& parsedLength) const String& emptyString() { - DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty())); + static NeverDestroyed<String> emptyString(StringImpl::empty()); + return emptyString; } diff --git a/Source/WTF/wtf/text/WTFString.h b/Source/WTF/wtf/text/WTFString.h index 3a915b13a..1c8e9097e 100644 --- a/Source/WTF/wtf/text/WTFString.h +++ b/Source/WTF/wtf/text/WTFString.h @@ -1,6 +1,6 @@ /* * (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -38,10 +38,6 @@ class QString; QT_END_NAMESPACE #endif -#if PLATFORM(WX) -class wxString; -#endif - #if PLATFORM(BLACKBERRY) namespace BlackBerry { namespace Platform { @@ -53,7 +49,6 @@ class String; namespace WTF { class CString; -class MemoryObjectInfo; struct StringHash; // Declarations of string operations @@ -110,8 +105,14 @@ public: // Construct a string by copying the contents of a vector. To avoid // copying, consider using String::adopt instead. - template<size_t inlineCapacity> - explicit String(const Vector<UChar, inlineCapacity>&); + // This method will never create a null string. Vectors with size() == 0 + // will return the empty string. + // NOTE: This is different from String(vector.data(), vector.size()) + // which will sometimes return a null string when vector.data() is null + // which can only occur for vectors without inline capacity. + // See: https://bugs.webkit.org/show_bug.cgi?id=109792 + template<size_t inlineCapacity, typename OverflowHandler> + explicit String(const Vector<UChar, inlineCapacity, OverflowHandler>&); // Construct a string with UTF-16 data, from a null-terminated source. WTF_EXPORT_STRING_API String(const UChar*); @@ -154,13 +155,14 @@ public: static String adopt(StringBuffer<LChar>& buffer) { return StringImpl::adopt(buffer); } static String adopt(StringBuffer<UChar>& buffer) { return StringImpl::adopt(buffer); } - template<typename CharacterType, size_t inlineCapacity> - static String adopt(Vector<CharacterType, inlineCapacity>& vector) { return StringImpl::adopt(vector); } + template<typename CharacterType, size_t inlineCapacity, typename OverflowHandler> + static String adopt(Vector<CharacterType, inlineCapacity, OverflowHandler>& vector) { return StringImpl::adopt(vector); } bool isNull() const { return !m_impl; } bool isEmpty() const { return !m_impl || !m_impl->length(); } StringImpl* impl() const { return m_impl.get(); } + PassRefPtr<StringImpl> releaseImpl() { return m_impl.release(); } unsigned length() const { @@ -254,6 +256,9 @@ public: size_t find(const LChar* str, unsigned start = 0) const { return m_impl ? m_impl->find(str, start) : notFound; } + size_t findNextLineStart(unsigned start = 0) const + { return m_impl ? m_impl->findNextLineStart(start) : notFound; } + // Find the last instance of a single character or string. size_t reverseFind(UChar c, unsigned start = UINT_MAX) const { return m_impl ? m_impl->reverseFind(c, start) : notFound; } @@ -276,7 +281,7 @@ public: size_t reverseFind(const String& str, unsigned start, bool caseSensitive) const { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); } - WTF_EXPORT_STRING_API const UChar* charactersWithNullTermination(); + WTF_EXPORT_STRING_API Vector<UChar> charactersWithNullTermination() const; WTF_EXPORT_STRING_API UChar32 characterStartingAt(unsigned) const; // Ditto. @@ -284,7 +289,9 @@ public: bool contains(const LChar* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } - bool startsWith(const String& s, bool caseSensitive = true) const + bool startsWith(const String& s) const + { return m_impl ? m_impl->startsWith(s.impl()) : s.isEmpty(); } + bool startsWith(const String& s, bool caseSensitive) const { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); } bool startsWith(UChar character) const { return m_impl ? m_impl->startsWith(character) : false; } @@ -393,7 +400,14 @@ public: bool percentage(int& percentage) const; +#if COMPILER_SUPPORTS(CXX_REFERENCE_QUALIFIED_FUNCTIONS) + WTF_EXPORT_STRING_API String isolatedCopy() const &; + WTF_EXPORT_STRING_API String isolatedCopy() const &&; +#else WTF_EXPORT_STRING_API String isolatedCopy() const; +#endif + + WTF_EXPORT_STRING_API bool isSafeToSendToAnotherThread() const; // Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that // allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*). @@ -421,17 +435,18 @@ public: WTF_EXPORT_STRING_API operator QString() const; #endif -#if PLATFORM(WX) - WTF_EXPORT_PRIVATE String(const wxString&); - WTF_EXPORT_PRIVATE operator wxString() const; -#endif - #if PLATFORM(BLACKBERRY) String(const BlackBerry::Platform::String&); operator BlackBerry::Platform::String() const; #endif WTF_EXPORT_STRING_API static String make8BitFrom16BitSource(const UChar*, size_t); + template<size_t inlineCapacity> + static String make8BitFrom16BitSource(const Vector<UChar, inlineCapacity>& buffer) + { + return make8BitFrom16BitSource(buffer.data(), buffer.size()); + } + WTF_EXPORT_STRING_API static String make16BitFrom8BitSource(const LChar*, size_t); // String::fromUTF8 will return a null string if @@ -440,6 +455,7 @@ public: WTF_EXPORT_STRING_API static String fromUTF8(const LChar*); static String fromUTF8(const char* s, size_t length) { return fromUTF8(reinterpret_cast<const LChar*>(s), length); }; static String fromUTF8(const char* s) { return fromUTF8(reinterpret_cast<const LChar*>(s)); }; + WTF_EXPORT_STRING_API static String fromUTF8(const CString&); // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8. WTF_EXPORT_STRING_API static String fromUTF8WithLatin1Fallback(const LChar*, size_t); @@ -479,6 +495,9 @@ private: template <typename CharacterType> void removeInternal(const CharacterType*, unsigned, int); + template <typename CharacterType> + void appendInternal(CharacterType); + RefPtr<StringImpl> m_impl; }; @@ -525,9 +544,9 @@ inline void swap(String& a, String& b) { a.swap(b); } // Definitions of string operations -template<size_t inlineCapacity> -String::String(const Vector<UChar, inlineCapacity>& vector) - : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0) +template<size_t inlineCapacity, typename OverflowHandler> +String::String(const Vector<UChar, inlineCapacity, OverflowHandler>& vector) + : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : StringImpl::empty()) { } @@ -599,7 +618,8 @@ inline bool codePointCompareLessThan(const String& a, const String& b) return codePointCompare(a.impl(), b.impl()) < 0; } -inline void append(Vector<UChar>& vector, const String& string) +template<size_t inlineCapacity> +inline void append(Vector<UChar, inlineCapacity>& vector, const String& string) { vector.append(string.characters(), string.length()); } diff --git a/Source/WTF/wtf/threads/BinarySemaphore.h b/Source/WTF/wtf/threads/BinarySemaphore.h index 8e82207e9..de51d4741 100644 --- a/Source/WTF/wtf/threads/BinarySemaphore.h +++ b/Source/WTF/wtf/threads/BinarySemaphore.h @@ -35,18 +35,18 @@ class BinarySemaphore { WTF_MAKE_NONCOPYABLE(BinarySemaphore); public: - BinarySemaphore(); - ~BinarySemaphore(); + WTF_EXPORT_PRIVATE BinarySemaphore(); + WTF_EXPORT_PRIVATE ~BinarySemaphore(); - void signal(); - bool wait(double absoluteTime); + WTF_EXPORT_PRIVATE void signal(); + WTF_EXPORT_PRIVATE bool wait(double absoluteTime); -#if PLATFORM(WIN) +#if OS(WINDOWS) HANDLE event() const { return m_event; } #endif private: -#if PLATFORM(WIN) +#if OS(WINDOWS) HANDLE m_event; #else bool m_isSet; diff --git a/Source/WTF/wtf/unicode/CharacterNames.h b/Source/WTF/wtf/unicode/CharacterNames.h index c36dfd0ef..076d911dc 100644 --- a/Source/WTF/wtf/unicode/CharacterNames.h +++ b/Source/WTF/wtf/unicode/CharacterNames.h @@ -38,6 +38,7 @@ namespace Unicode { const UChar32 aegeanWordSeparatorLine = 0x10100; const UChar32 aegeanWordSeparatorDot = 0x10101; +const UChar apostrophe = 0x0027; const UChar blackCircle = 0x25CF; const UChar blackSquare = 0x25A0; const UChar blackUpPointingTriangle = 0x25B2; @@ -47,6 +48,7 @@ const UChar carriageReturn = 0x000D; const UChar ethiopicPrefaceColon = 0x1366; const UChar ethiopicWordspace = 0x1361; const UChar fisheye = 0x25C9; +const UChar quotationMark = 0x0022; const UChar hebrewPunctuationGeresh = 0x05F3; const UChar hebrewPunctuationGershayim = 0x05F4; const UChar HiraganaLetterSmallA = 0x3041; diff --git a/Source/WTF/wtf/unicode/Collator.h b/Source/WTF/wtf/unicode/Collator.h index 7994ff8e5..67d4e22a3 100644 --- a/Source/WTF/wtf/unicode/Collator.h +++ b/Source/WTF/wtf/unicode/Collator.h @@ -49,7 +49,7 @@ namespace WTF { WTF_EXPORT_PRIVATE ~Collator(); WTF_EXPORT_PRIVATE void setOrderLowerFirst(bool); - static PassOwnPtr<Collator> userDefault(); + WTF_EXPORT_PRIVATE static PassOwnPtr<Collator> userDefault(); WTF_EXPORT_PRIVATE Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const; diff --git a/Source/WTF/wtf/unicode/UTF8.h b/Source/WTF/wtf/unicode/UTF8.h index 1fc21baad..e95cc1288 100644 --- a/Source/WTF/wtf/unicode/UTF8.h +++ b/Source/WTF/wtf/unicode/UTF8.h @@ -34,12 +34,12 @@ namespace Unicode { // Given a first byte, gives the length of the UTF-8 sequence it begins. // Returns 0 for bytes that are not legal starts of UTF-8 sequences. // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF). - int UTF8SequenceLength(char); + WTF_EXPORT_PRIVATE int UTF8SequenceLength(char); // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character. // Only allows Unicode characters (U-00000000 to U-0010FFFF). // Returns -1 if the sequence is not valid (including presence of extra bytes). - int decodeUTF8Sequence(const char*); + WTF_EXPORT_PRIVATE int decodeUTF8Sequence(const char*); typedef enum { conversionOK, // conversion successful diff --git a/Source/WTF/wtf/unicode/Unicode.h b/Source/WTF/wtf/unicode/Unicode.h index 926021191..c76418430 100644 --- a/Source/WTF/wtf/unicode/Unicode.h +++ b/Source/WTF/wtf/unicode/Unicode.h @@ -28,12 +28,8 @@ // Define platform neutral 8 bit character type (L is for Latin-1). typedef unsigned char LChar; -#if USE(QT4_UNICODE) -#include "qt4/UnicodeQt4.h" -#elif USE(ICU_UNICODE) +#if USE(ICU_UNICODE) #include <wtf/unicode/icu/UnicodeIcu.h> -#elif USE(GLIB_UNICODE) -#include <wtf/unicode/glib/UnicodeGLib.h> #elif USE(WCHAR_UNICODE) #include <wtf/unicode/wchar/UnicodeWchar.h> #else diff --git a/Source/WTF/wtf/unicode/glib/UnicodeGLib.cpp b/Source/WTF/wtf/unicode/glib/UnicodeGLib.cpp deleted file mode 100644 index 80409852d..000000000 --- a/Source/WTF/wtf/unicode/glib/UnicodeGLib.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> - * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> - * Copyright (C) 2010 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "UnicodeGLib.h" - -#include <wtf/Vector.h> -#include <wtf/unicode/UTF8.h> - -#define UTF8_IS_SURROGATE(character) (character >= 0x10000 && character <= 0x10FFFF) - -namespace WTF { -namespace Unicode { - -UChar32 foldCase(UChar32 ch) -{ - GOwnPtr<GError> gerror; - - GOwnPtr<char> utf8char; - utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr())); - if (gerror) - return ch; - - GOwnPtr<char> utf8caseFolded; - utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1)); - - GOwnPtr<gunichar> ucs4Result; - ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0)); - - return *ucs4Result; -} - -static int getUTF16LengthFromUTF8(const gchar* utf8String, int length) -{ - int utf16Length = 0; - const gchar* inputString = utf8String; - - while ((utf8String + length - inputString > 0) && *inputString) { - gunichar character = g_utf8_get_char(inputString); - - utf16Length += UTF8_IS_SURROGATE(character) ? 2 : 1; - inputString = g_utf8_next_char(inputString); - } - - return utf16Length; -} - -typedef gchar* (*UTF8CaseFunction)(const gchar*, gssize length); - -static int convertCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error, UTF8CaseFunction caseFunction) -{ - *error = false; - - // Allocate a buffer big enough to hold all the characters. - Vector<char> buffer(srcLength * 3); - char* utf8Target = buffer.data(); - const UChar* utf16Source = src; - ConversionResult conversionResult = convertUTF16ToUTF8(&utf16Source, utf16Source + srcLength, &utf8Target, utf8Target + buffer.size(), true); - if (conversionResult != conversionOK) { - *error = true; - return -1; - } - buffer.shrink(utf8Target - buffer.data()); - - GOwnPtr<char> utf8Result(caseFunction(buffer.data(), buffer.size())); - long utf8ResultLength = strlen(utf8Result.get()); - - // Calculate the destination buffer size. - int realLength = getUTF16LengthFromUTF8(utf8Result.get(), utf8ResultLength); - if (realLength > resultLength) { - *error = true; - return realLength; - } - - // Convert the result to UTF-16. - UChar* utf16Target = result; - const char* utf8Source = utf8Result.get(); - bool unusedISAllASCII; - conversionResult = convertUTF8ToUTF16(&utf8Source, utf8Source + utf8ResultLength, &utf16Target, utf16Target + resultLength, &unusedIsAllASCII, true); - long utf16ResultLength = utf16Target - result; - if (conversionResult != conversionOK) - *error = true; - - return utf16ResultLength <= 0 ? -1 : utf16ResultLength; -} -int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_casefold); -} - -int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_strdown); -} - -int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_strup); -} - -Direction direction(UChar32 c) -{ - PangoBidiType type = pango_bidi_type_for_unichar(c); - switch (type) { - case PANGO_BIDI_TYPE_L: - return LeftToRight; - case PANGO_BIDI_TYPE_R: - return RightToLeft; - case PANGO_BIDI_TYPE_AL: - return RightToLeftArabic; - case PANGO_BIDI_TYPE_LRE: - return LeftToRightEmbedding; - case PANGO_BIDI_TYPE_RLE: - return RightToLeftEmbedding; - case PANGO_BIDI_TYPE_LRO: - return LeftToRightOverride; - case PANGO_BIDI_TYPE_RLO: - return RightToLeftOverride; - case PANGO_BIDI_TYPE_PDF: - return PopDirectionalFormat; - case PANGO_BIDI_TYPE_EN: - return EuropeanNumber; - case PANGO_BIDI_TYPE_AN: - return ArabicNumber; - case PANGO_BIDI_TYPE_ES: - return EuropeanNumberSeparator; - case PANGO_BIDI_TYPE_ET: - return EuropeanNumberTerminator; - case PANGO_BIDI_TYPE_CS: - return CommonNumberSeparator; - case PANGO_BIDI_TYPE_NSM: - return NonSpacingMark; - case PANGO_BIDI_TYPE_BN: - return BoundaryNeutral; - case PANGO_BIDI_TYPE_B: - return BlockSeparator; - case PANGO_BIDI_TYPE_S: - return SegmentSeparator; - case PANGO_BIDI_TYPE_WS: - return WhiteSpaceNeutral; - default: - return OtherNeutral; - } -} - -int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - GOwnPtr<char> utf8a; - GOwnPtr<char> utf8b; - - utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0)); - utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0)); - - GOwnPtr<char> foldedA; - GOwnPtr<char> foldedB; - - foldedA.set(g_utf8_casefold(utf8a.get(), -1)); - foldedB.set(g_utf8_casefold(utf8b.get(), -1)); - - // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu - // from the ICU docs: - // "Compare two strings case-insensitively using full case folding. - // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))." - // - // So it looks like we don't need the full g_utf8_collate here, - // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes). - // As there is no direct equivalent to this icu function in GLib, for now - // we'll use g_utf8_collate(): - - return g_utf8_collate(foldedA.get(), foldedB.get()); -} - -} -} diff --git a/Source/WTF/wtf/unicode/glib/UnicodeGLib.h b/Source/WTF/wtf/unicode/glib/UnicodeGLib.h deleted file mode 100644 index 89c9b1fb7..000000000 --- a/Source/WTF/wtf/unicode/glib/UnicodeGLib.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> - * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef UnicodeGLib_h -#define UnicodeGLib_h - -#include <wtf/gobject/GOwnPtr.h> -#include <wtf/unicode/ScriptCodesFromICU.h> -#include <wtf/unicode/UnicodeMacrosFromICU.h> - -#include <glib.h> -#include <pango/pango.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -typedef uint16_t UChar; -typedef int32_t UChar32; - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight, - RightToLeft, - EuropeanNumber, - EuropeanNumberSeparator, - EuropeanNumberTerminator, - ArabicNumber, - CommonNumberSeparator, - BlockSeparator, - SegmentSeparator, - WhiteSpaceNeutral, - OtherNeutral, - LeftToRightEmbedding, - LeftToRightOverride, - RightToLeftArabic, - RightToLeftEmbedding, - RightToLeftOverride, - PopDirectionalFormat, - NonSpacingMark, - BoundaryNeutral -}; - -enum DecompositionType { - DecompositionNone, - DecompositionCanonical, - DecompositionCompat, - DecompositionCircle, - DecompositionFinal, - DecompositionFont, - DecompositionFraction, - DecompositionInitial, - DecompositionIsolated, - DecompositionMedial, - DecompositionNarrow, - DecompositionNoBreak, - DecompositionSmall, - DecompositionSquare, - DecompositionSub, - DecompositionSuper, - DecompositionVertical, - DecompositionWide, -}; - -enum CharCategory { - NoCategory = 0, - Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED), - Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER), - Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER), - Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER), - Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER), - Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER), - - Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK), - Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK), - Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK), - - Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER), - Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER), - Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER), - - Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR), - Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR), - Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR), - - Other_Control = U_MASK(G_UNICODE_CONTROL), - Other_Format = U_MASK(G_UNICODE_FORMAT), - Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE), - Other_Surrogate = U_MASK(G_UNICODE_SURROGATE), - - Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION), - Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION), - Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION), - Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION), - Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION), - - Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL), - Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL), - Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL), - Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL), - - Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION), - Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION) -}; - -UChar32 foldCase(UChar32); - -int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -inline UChar32 toLower(UChar32 c) -{ - return g_unichar_tolower(c); -} - -inline UChar32 toUpper(UChar32 c) -{ - return g_unichar_toupper(c); -} - -int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -inline UChar32 toTitleCase(UChar32 c) -{ - return g_unichar_totitle(c); -} - -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool isAlphanumeric(UChar32 c) -{ - return g_unichar_isalnum(c); -} - -inline bool isFormatChar(UChar32 c) -{ - return g_unichar_type(c) == G_UNICODE_FORMAT; -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR; -} - -inline bool isPrintableChar(UChar32 c) -{ - return g_unichar_isprint(c); -} - -inline bool isDigit(UChar32 c) -{ - return g_unichar_isdigit(c); -} - -inline bool isPunct(UChar32 c) -{ - return g_unichar_ispunct(c); -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32 c) -{ - // FIXME - return false; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - gunichar mirror = 0; - g_unichar_get_mirror_char(c, &mirror); - return mirror; -} - -inline CharCategory category(UChar32 c) -{ - if (c > 0xffff) - return NoCategory; - - return (CharCategory) U_MASK(g_unichar_type(c)); -} - -Direction direction(UChar32); - -inline bool isLower(UChar32 c) -{ - return g_unichar_islower(c); -} - -inline uint8_t combiningClass(UChar32 c) -{ - // FIXME - // return g_unichar_combining_class(c); - return 0; -} - -inline DecompositionType decompositionType(UChar32 c) -{ - // FIXME - return DecompositionNone; -} - -int umemcasecmp(const UChar*, const UChar*, int len); - -} -} - -#endif - diff --git a/Source/WTF/wtf/unicode/icu/CollatorICU.cpp b/Source/WTF/wtf/unicode/icu/CollatorICU.cpp index 72a86620e..c74f148d1 100644 --- a/Source/WTF/wtf/unicode/icu/CollatorICU.cpp +++ b/Source/WTF/wtf/unicode/icu/CollatorICU.cpp @@ -62,11 +62,11 @@ PassOwnPtr<Collator> Collator::userDefault() { #if OS(DARWIN) && USE(CF) // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. -#if !OS(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent()); +#if !OS(IOS) + RetainPtr<CFLocaleRef> currentLocale = adoptCF(CFLocaleCopyCurrent()); CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier); #else - RetainPtr<CFStringRef> collationOrderRetainer(AdoptCF, (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)); + RetainPtr<CFStringRef> collationOrderRetainer = adoptCF((CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)); CFStringRef collationOrder = collationOrderRetainer.get(); #endif char buf[256]; @@ -148,6 +148,6 @@ void Collator::releaseCollator() } } -} +} // namespace WTF -#endif +#endif // USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION diff --git a/Source/WTF/wtf/unicode/icu/UnicodeIcu.h b/Source/WTF/wtf/unicode/icu/UnicodeIcu.h index 962e7320a..4867f6552 100644 --- a/Source/WTF/wtf/unicode/icu/UnicodeIcu.h +++ b/Source/WTF/wtf/unicode/icu/UnicodeIcu.h @@ -23,6 +23,8 @@ #ifndef WTF_UNICODE_ICU_H #define WTF_UNICODE_ICU_H +#if USE(ICU_UNICODE) + #include <stdlib.h> #include <unicode/uchar.h> #include <unicode/uscript.h> @@ -30,6 +32,7 @@ #include <unicode/utf16.h> namespace WTF { + namespace Unicode { enum Direction { @@ -225,6 +228,10 @@ inline int umemcasecmp(const UChar* a, const UChar* b, int len) return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT); } -} } +} // namespace Unicode + +} // namespace WTF + +#endif // USE(ICU_UNICODE) #endif // WTF_UNICODE_ICU_H diff --git a/Source/WTF/wtf/unicode/qt4/UnicodeQt4.h b/Source/WTF/wtf/unicode/qt4/UnicodeQt4.h deleted file mode 100644 index a2d1ad4c1..000000000 --- a/Source/WTF/wtf/unicode/qt4/UnicodeQt4.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_UNICODE_QT4_H -#define WTF_UNICODE_QT4_H - -#include <wtf/unicode/ScriptCodesFromICU.h> -#include <wtf/unicode/UnicodeMacrosFromICU.h> - -#include <QChar> -#include <QString> - -#include <config.h> - -#include <stdint.h> -#if USE(ICU_UNICODE) -#include <unicode/ubrk.h> -#endif - -QT_BEGIN_NAMESPACE -namespace QUnicodeTables { - struct Properties { - ushort category : 8; - ushort line_break_class : 8; - ushort direction : 8; - ushort combiningClass :8; - ushort joining : 2; - signed short digitValue : 6; /* 5 needed */ - ushort unicodeVersion : 4; - ushort lowerCaseSpecial : 1; - ushort upperCaseSpecial : 1; - ushort titleCaseSpecial : 1; - ushort caseFoldSpecial : 1; /* currently unused */ - signed short mirrorDiff : 16; - signed short lowerCaseDiff : 16; - signed short upperCaseDiff : 16; - signed short titleCaseDiff : 16; - signed short caseFoldDiff : 16; - }; - Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4); - Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2); -} -QT_END_NAMESPACE - -// ugly hack to make UChar compatible with JSChar in API/JSStringRef.h -#if defined(Q_OS_WIN) || (COMPILER(RVCT) && !OS(LINUX)) -typedef wchar_t UChar; -#else -typedef uint16_t UChar; -#endif - -#if !USE(ICU_UNICODE) -typedef uint32_t UChar32; -#endif - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight = QChar::DirL, - RightToLeft = QChar::DirR, - EuropeanNumber = QChar::DirEN, - EuropeanNumberSeparator = QChar::DirES, - EuropeanNumberTerminator = QChar::DirET, - ArabicNumber = QChar::DirAN, - CommonNumberSeparator = QChar::DirCS, - BlockSeparator = QChar::DirB, - SegmentSeparator = QChar::DirS, - WhiteSpaceNeutral = QChar::DirWS, - OtherNeutral = QChar::DirON, - LeftToRightEmbedding = QChar::DirLRE, - LeftToRightOverride = QChar::DirLRO, - RightToLeftArabic = QChar::DirAL, - RightToLeftEmbedding = QChar::DirRLE, - RightToLeftOverride = QChar::DirRLO, - PopDirectionalFormat = QChar::DirPDF, - NonSpacingMark = QChar::DirNSM, - BoundaryNeutral = QChar::DirBN -}; - -enum DecompositionType { - DecompositionNone = QChar::NoDecomposition, - DecompositionCanonical = QChar::Canonical, - DecompositionCompat = QChar::Compat, - DecompositionCircle = QChar::Circle, - DecompositionFinal = QChar::Final, - DecompositionFont = QChar::Font, - DecompositionFraction = QChar::Fraction, - DecompositionInitial = QChar::Initial, - DecompositionIsolated = QChar::Isolated, - DecompositionMedial = QChar::Medial, - DecompositionNarrow = QChar::Narrow, - DecompositionNoBreak = QChar::NoBreak, - DecompositionSmall = QChar::Small, - DecompositionSquare = QChar::Square, - DecompositionSub = QChar::Sub, - DecompositionSuper = QChar::Super, - DecompositionVertical = QChar::Vertical, - DecompositionWide = QChar::Wide -}; - -enum CharCategory { - NoCategory = 0, - Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing), - Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining), - Mark_Enclosing = U_MASK(QChar::Mark_Enclosing), - Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit), - Number_Letter = U_MASK(QChar::Number_Letter), - Number_Other = U_MASK(QChar::Number_Other), - Separator_Space = U_MASK(QChar::Separator_Space), - Separator_Line = U_MASK(QChar::Separator_Line), - Separator_Paragraph = U_MASK(QChar::Separator_Paragraph), - Other_Control = U_MASK(QChar::Other_Control), - Other_Format = U_MASK(QChar::Other_Format), - Other_Surrogate = U_MASK(QChar::Other_Surrogate), - Other_PrivateUse = U_MASK(QChar::Other_PrivateUse), - Other_NotAssigned = U_MASK(QChar::Other_NotAssigned), - Letter_Uppercase = U_MASK(QChar::Letter_Uppercase), - Letter_Lowercase = U_MASK(QChar::Letter_Lowercase), - Letter_Titlecase = U_MASK(QChar::Letter_Titlecase), - Letter_Modifier = U_MASK(QChar::Letter_Modifier), - Letter_Other = U_MASK(QChar::Letter_Other), - Punctuation_Connector = U_MASK(QChar::Punctuation_Connector), - Punctuation_Dash = U_MASK(QChar::Punctuation_Dash), - Punctuation_Open = U_MASK(QChar::Punctuation_Open), - Punctuation_Close = U_MASK(QChar::Punctuation_Close), - Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote), - Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote), - Punctuation_Other = U_MASK(QChar::Punctuation_Other), - Symbol_Math = U_MASK(QChar::Symbol_Math), - Symbol_Currency = U_MASK(QChar::Symbol_Currency), - Symbol_Modifier = U_MASK(QChar::Symbol_Modifier), - Symbol_Other = U_MASK(QChar::Symbol_Other) -}; - - -// FIXME: handle surrogates correctly in all methods - -inline UChar32 toLower(UChar32 ch) -{ - return QChar::toLower(uint32_t(ch)); -} - -inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - const UChar *e = src + srcLength; - const UChar *s = src; - UChar *r = result; - uint rindex = 0; - - // this avoids one out of bounds check in the loop - if (s < e && QChar(*s).isLowSurrogate()) { - if (r) - r[rindex] = *s++; - ++rindex; - } - - int needed = 0; - while (s < e && (rindex < uint(resultLength) || !r)) { - uint c = *s; - if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate()) - c = QChar::surrogateToUcs4(*(s - 1), c); - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c); - if (prop->lowerCaseSpecial) { - QString qstring; - if (c < 0x10000) { - qstring += QChar(c); - } else { - qstring += QChar(*(s-1)); - qstring += QChar(*s); - } - qstring = qstring.toLower(); - for (int i = 0; i < qstring.length(); ++i) { - if (rindex >= uint(resultLength)) { - needed += qstring.length() - i; - break; - } - if (r) - r[rindex] = qstring.at(i).unicode(); - ++rindex; - } - } else { - if (r) - r[rindex] = *s + prop->lowerCaseDiff; - ++rindex; - } - ++s; - } - if (s < e) - needed += e - s; - *error = (needed != 0); - if (rindex < uint(resultLength)) - r[rindex] = 0; - return rindex + needed; -} - -inline UChar32 toUpper(UChar32 c) -{ - return QChar::toUpper(uint32_t(c)); -} - -inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - const UChar *e = src + srcLength; - const UChar *s = src; - UChar *r = result; - int rindex = 0; - - // this avoids one out of bounds check in the loop - if (s < e && QChar(*s).isLowSurrogate()) { - if (r) - r[rindex] = *s++; - ++rindex; - } - - int needed = 0; - while (s < e && (rindex < resultLength || !r)) { - uint c = *s; - if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate()) - c = QChar::surrogateToUcs4(*(s - 1), c); - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c); - if (prop->upperCaseSpecial) { - QString qstring; - if (c < 0x10000) { - qstring += QChar(c); - } else { - qstring += QChar(*(s-1)); - qstring += QChar(*s); - } - qstring = qstring.toUpper(); - for (int i = 0; i < qstring.length(); ++i) { - if (rindex >= resultLength) { - needed += qstring.length() - i; - break; - } - if (r) - r[rindex] = qstring.at(i).unicode(); - ++rindex; - } - } else { - if (r) - r[rindex] = *s + prop->upperCaseDiff; - ++rindex; - } - ++s; - } - if (s < e) - needed += e - s; - *error = (needed != 0); - if (rindex < resultLength) - r[rindex] = 0; - return rindex + needed; -} - -inline int toTitleCase(UChar32 c) -{ - return QChar::toTitleCase(uint32_t(c)); -} - -inline UChar32 foldCase(UChar32 c) -{ - return QChar::toCaseFolded(uint32_t(c)); -} - -inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - // FIXME: handle special casing. Easiest with some low level API in Qt - *error = false; - if (resultLength < srcLength) { - *error = true; - return srcLength; - } - for (int i = 0; i < srcLength; ++i) - result[i] = QChar::toCaseFolded(ushort(src[i])); - return srcLength; -} - -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool isPrintableChar(UChar32 c) -{ - const uint test = U_MASK(QChar::Other_Control) | - U_MASK(QChar::Other_NotAssigned); - return !(U_MASK(QChar::category(uint32_t(c))) & test); -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return QChar::category(uint32_t(c)) == QChar::Separator_Space; -} - -inline bool isPunct(UChar32 c) -{ - const uint test = U_MASK(QChar::Punctuation_Connector) | - U_MASK(QChar::Punctuation_Dash) | - U_MASK(QChar::Punctuation_Open) | - U_MASK(QChar::Punctuation_Close) | - U_MASK(QChar::Punctuation_InitialQuote) | - U_MASK(QChar::Punctuation_FinalQuote) | - U_MASK(QChar::Punctuation_Other); - return U_MASK(QChar::category(uint32_t(c))) & test; -} - -inline bool isLower(UChar32 c) -{ - return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase; -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32) -{ - // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context). - return false; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - return QChar::mirroredChar(uint32_t(c)); -} - -inline uint8_t combiningClass(UChar32 c) -{ - return QChar::combiningClass(uint32_t(c)); -} - -inline DecompositionType decompositionType(UChar32 c) -{ - return (DecompositionType)QChar::decompositionTag(c); -} - -inline int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - // handle surrogates correctly - for (int i = 0; i < len; ++i) { - uint c1 = QChar::toCaseFolded(ushort(a[i])); - uint c2 = QChar::toCaseFolded(ushort(b[i])); - if (c1 != c2) - return c1 - c2; - } - return 0; -} - -inline Direction direction(UChar32 c) -{ - return (Direction)QChar::direction(uint32_t(c)); -} - -inline CharCategory category(UChar32 c) -{ - return (CharCategory) U_MASK(QChar::category(uint32_t(c))); -} - -} // namespace Unicode -} // namespace WTF - -#endif // WTF_UNICODE_QT4_H diff --git a/Source/WTF/wtf/url/api/ParsedURL.cpp b/Source/WTF/wtf/url/api/ParsedURL.cpp deleted file mode 100644 index c4a56699b..000000000 --- a/Source/WTF/wtf/url/api/ParsedURL.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. All Rights Reserved. - * 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 "ParsedURL.h" - -#if USE(WTFURL) - -#include <wtf/DataLog.h> -#include <wtf/RawURLBuffer.h> -#include <wtf/URLComponent.h> -#include <wtf/URLUtil.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringImpl.h> - -namespace WTF { - -ParsedURL::ParsedURL(const String& urlString, ParsedURLStringTag) -{ - unsigned urlStringLength = urlString.length(); - if (!urlStringLength) - return; // FIXME: we should ASSERT on this, but people use KURL incorrectly with ParsedURLStringTag :(. - - RawURLBuffer<char> outputBuffer; - String base; - const CString& baseStr = base.utf8(); - bool isValid = false; - URLSegments baseSegments; - - // FIXME: we should take shortcuts here! We do not have to resolve the relative part. - if (urlString.is8Bit()) - isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, - reinterpret_cast<const char*>(urlString.characters8()), urlStringLength, - /* charsetConverter */ 0, - outputBuffer, &m_segments); - else - isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, - urlString.characters16(), urlStringLength, - /* charsetConverter */ 0, - outputBuffer, &m_segments); - - // FIXME: we should ASSERT on isValid, but people use KURL incorrectly with ParsedURLStringTag :(. - if (isValid) - m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); -} - -ParsedURL::ParsedURL(const String& urlString, URLQueryCharsetConverter* queryCharsetConverter) -{ - unsigned urlStringLength = urlString.length(); - if (!urlStringLength) - return; - - RawURLBuffer<char> outputBuffer; - String base; - const CString& baseStr = base.utf8(); - bool isValid = false; - URLSegments baseSegments; - - // FIXME: we should take shortcuts here! We do not have to resolve the relative part. - if (urlString.is8Bit()) - isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, - reinterpret_cast<const char*>(urlString.characters8()), urlStringLength, - queryCharsetConverter, - outputBuffer, &m_segments); - else - isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, - urlString.characters16(), urlStringLength, - queryCharsetConverter, - outputBuffer, &m_segments); - - if (isValid) - m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); -} - -ParsedURL::ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter* queryCharsetConverter) -{ - if (!base.isValid()) - return; - - unsigned relativeLength = relative.length(); - if (!relativeLength) { - *this = base.withoutFragment(); - return; - } - - RawURLBuffer<char> outputBuffer; - const CString& baseStr = base.m_spec.m_string.utf8(); - bool isValid = false; - - if (relative.is8Bit()) - isValid = URLUtilities::resolveRelative(baseStr.data(), base.m_segments, - reinterpret_cast<const char*>(relative.characters8()), relativeLength, - queryCharsetConverter, - outputBuffer, &m_segments); - else - isValid = URLUtilities::resolveRelative(baseStr.data(), base.m_segments, - relative.characters16(), relativeLength, - queryCharsetConverter, - outputBuffer, &m_segments); - - if (isValid) - m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); -} - -ParsedURL ParsedURL::isolatedCopy() const -{ - ParsedURL copy; - copy.m_segments = this->m_segments; - copy.m_spec = URLString(this->m_spec.string().isolatedCopy()); - return copy; -} - -String ParsedURL::scheme() const -{ - return segment(m_segments.scheme); -} - -bool ParsedURL::hasStandardScheme() const -{ - ASSERT(m_segments.scheme.isValid()); - const String& urlStringSpec = m_spec.m_string; - if (urlStringSpec.is8Bit()) - return URLUtilities::isStandard(urlStringSpec.characters8(), m_segments.scheme); - return URLUtilities::isStandard(urlStringSpec.characters16(), 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); -} - -bool ParsedURL::hasPort() const -{ - return m_segments.port.isNonEmpty(); -} - -String ParsedURL::port() const -{ - return segment(m_segments.port); -} - -template<typename CharacterType> -static inline String generateNewSpecWithPort(const String& spec, unsigned newSpecLength, unsigned portDelimiterPosition, const LChar* portString, unsigned portStringLength, unsigned postPortPositionInSource) -{ - ASSERT(newSpecLength == portDelimiterPosition + 1 + portStringLength + (spec.length() - postPortPositionInSource)); - - CharacterType* buffer; - String newSpec = StringImpl::createUninitialized(newSpecLength, buffer); - - // Copy everything prior to the port posisiton. - ASSERT(buffer + portDelimiterPosition < buffer + newSpecLength); - StringImpl::copyChars(buffer, spec.getCharacters<CharacterType>(), portDelimiterPosition); - - // Add the new port from the position. - buffer[portDelimiterPosition] = ':'; - unsigned portPosition = portDelimiterPosition + 1; - ASSERT(buffer + portPosition + portStringLength <= buffer + newSpecLength); - StringImpl::copyChars(buffer + portPosition, portString, portStringLength); - - // Copy the character post-port from the source. - unsigned remainingComponentsPositionInDestination = portPosition + portStringLength; - ASSERT(buffer + remainingComponentsPositionInDestination + (spec.length() - postPortPositionInSource) == buffer + newSpecLength); - StringImpl::copyChars(buffer + remainingComponentsPositionInDestination, &(spec.getCharacters<CharacterType>()[postPortPositionInSource]), spec.length() - postPortPositionInSource); - - return newSpec; -} - -static inline void replacePortWithString(String& spec, URLSegments& segments, const LChar* portString, unsigned portStringLength) -{ - // Compute the new spec length. - int lengthDifference; - const URLComponent oldPortComponent = segments.port; - if (oldPortComponent.isValid()) - lengthDifference = portStringLength - oldPortComponent.length(); - else - lengthDifference = 1 + portStringLength; - unsigned newLength = spec.length() + lengthDifference; - - // Find the substring positions for the generator template. - int portDelimiterPosition = segments.charactersBefore(URLSegments::Port, URLSegments::DelimiterIncluded); - ASSERT(portDelimiterPosition > 0); - - unsigned postPortPositionInSource; - if (oldPortComponent.isValid()) - postPortPositionInSource = oldPortComponent.end(); - else - postPortPositionInSource = portDelimiterPosition; - - // Create the new spec with portString. - if (spec.is8Bit()) - spec = generateNewSpecWithPort<LChar>(spec, newLength, static_cast<unsigned>(portDelimiterPosition), portString, portStringLength, postPortPositionInSource); - else - spec = generateNewSpecWithPort<UChar>(spec, newLength, static_cast<unsigned>(portDelimiterPosition), portString, portStringLength, postPortPositionInSource); - - // Update the URL components. - unsigned portPosition = portDelimiterPosition + 1; - segments.port.setBegin(portPosition); - segments.port.setLength(portStringLength); - segments.moveFromComponentBy(URLSegments::Path, lengthDifference); -} - - -void ParsedURL::replacePort(unsigned short newPort) -{ - ASSERT(hasStandardScheme()); - - // Generate a char* string for the port number. - LChar buf[5]; - LChar* end = buf + WTF_ARRAY_LENGTH(buf); - LChar* p = end; - do { - *--p = static_cast<LChar>((newPort % 10) + '0'); - newPort /= 10; - } while (newPort); - const unsigned portStringLength = end - p; - - replacePortWithString(m_spec.m_string, m_segments, p, portStringLength); -} - -void ParsedURL::removePort() -{ - if (!hasPort()) - return; - - // 1) Remove the port from the spec, including the delimiter. - String newSpec; - int beginning = m_segments.port.begin() - 1; - unsigned length = m_segments.port.length() + 1; - - String newSpecString = m_spec.string(); - newSpecString.remove(beginning, length); - m_spec = URLString(newSpecString); - - // 2) Update the components positions. - m_segments.port.reset(); - m_segments.moveFromComponentBy(URLSegments::Path, -length); -} - -String ParsedURL::path() const -{ - return segment(m_segments.path); -} - -String ParsedURL::query() const -{ - return segment(m_segments.query); -} - -bool ParsedURL::hasFragment() const -{ - return m_segments.fragment.isValid(); -} - -String ParsedURL::fragment() const -{ - return segment(m_segments.fragment); -} - -ParsedURL ParsedURL::withoutFragment() const -{ - if (!hasFragment()) - return *this; - - ParsedURL newURL; - - int charactersBeforeFragemnt = m_segments.charactersBefore(URLSegments::Fragment, URLSegments::DelimiterExcluded); - newURL.m_spec = URLString(m_spec.string().substringSharingImpl(0, charactersBeforeFragemnt)); - - newURL.m_segments = m_segments; - newURL.m_segments.fragment = URLComponent(); - return newURL; -} - -String ParsedURL::baseAsString() const -{ - // FIXME: Add WTFURL Implementation. - return String(); -} - -String ParsedURL::segment(const URLComponent& component) const -{ - ASSERT(isValid()); - - if (!component.isValid()) - return String(); - - String segment = m_spec.string().substring(component.begin(), component.length()); - - // FIXME: GoogleURL create empty segments. This happen for the fragment for the test fast/url/segments.html - // ASSERT_WITH_MESSAGE(!segment.isEmpty(), "A valid URL component should not be empty."); - return segment; -} - -#ifndef NDEBUG - -#define SHOW_COMPONENT(parsedURL, componentName) \ - if (!parsedURL->componentName().isNull()) { \ - dataLog(" " #componentName " = "); \ - parsedURL->componentName().show(); \ - } - -void ParsedURL::print() const -{ - if (!isValid()) { - dataLog("Invalid ParsedURL.\n"); - return; - } - - dataLog("Valid ParsedURL with:\n"); - dataLog(" m_spec = "); - m_spec.print(); - - SHOW_COMPONENT(this, scheme); - SHOW_COMPONENT(this, username); - SHOW_COMPONENT(this, password); - SHOW_COMPONENT(this, host); - SHOW_COMPONENT(this, port); - SHOW_COMPONENT(this, path); - SHOW_COMPONENT(this, query); - SHOW_COMPONENT(this, fragment); -} -#endif - -} - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/api/ParsedURL.h b/Source/WTF/wtf/url/api/ParsedURL.h deleted file mode 100644 index c2cbb9cd2..000000000 --- a/Source/WTF/wtf/url/api/ParsedURL.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. All Rights Reserved. - * 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 ParsedURL_h -#define ParsedURL_h - -#if USE(WTFURL) - -#include <wtf/url/api/URLString.h> -#include <wtf/url/src/URLSegments.h> - -namespace WTF { - -class URLComponent; -class URLQueryCharsetConverter; - -// ParsedURL represents a valid URL decomposed by components. -class ParsedURL { -public: - enum ParsedURLStringTag { ParsedURLString }; - - ParsedURL() { }; - WTF_EXPORT_PRIVATE explicit ParsedURL(const String&, ParsedURLStringTag); - - WTF_EXPORT_PRIVATE explicit ParsedURL(const String&, URLQueryCharsetConverter*); - WTF_EXPORT_PRIVATE explicit ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter*); - - WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const; - - bool isValid() const { return !m_spec.string().isNull(); } - - // Return a URL component or a null String if the component is undefined for the URL. - WTF_EXPORT_PRIVATE String scheme() const; - WTF_EXPORT_PRIVATE bool hasStandardScheme() const; - - WTF_EXPORT_PRIVATE String username() const; - WTF_EXPORT_PRIVATE String password() const; - WTF_EXPORT_PRIVATE String host() const; - - WTF_EXPORT_PRIVATE bool hasPort() const; - WTF_EXPORT_PRIVATE String port() const; - WTF_EXPORT_PRIVATE void replacePort(unsigned short newPort); - WTF_EXPORT_PRIVATE void removePort(); - - WTF_EXPORT_PRIVATE String path() const; - WTF_EXPORT_PRIVATE String query() const; - - WTF_EXPORT_PRIVATE bool hasFragment() const; - WTF_EXPORT_PRIVATE String fragment() const; - WTF_EXPORT_PRIVATE ParsedURL withoutFragment() const; - - - WTF_EXPORT_PRIVATE String baseAsString() const; - - const URLString& spec() const { return m_spec; } - -#ifndef NDEBUG - WTF_EXPORT_PRIVATE void print() const; -#endif - -private: - inline String segment(const URLComponent&) const; - - URLString m_spec; - URLSegments m_segments; -}; - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/WTF/wtf/url/api/URLBuffer.h b/Source/WTF/wtf/url/api/URLBuffer.h deleted file mode 100644 index 6eccd04fa..000000000 --- a/Source/WTF/wtf/url/api/URLBuffer.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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/WTF/wtf/url/api/URLQueryCharsetConverter.h b/Source/WTF/wtf/url/api/URLQueryCharsetConverter.h deleted file mode 100644 index 5771a42e4..000000000 --- a/Source/WTF/wtf/url/api/URLQueryCharsetConverter.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 URLQueryCharsetConverter_h -#define URLQueryCharsetConverter_h - -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -template<typename CharacterType> class URLBuffer; - -class URLQueryCharsetConverter { -public: - URLQueryCharsetConverter() { } - virtual ~URLQueryCharsetConverter() { } - virtual void convertFromUTF16(const UChar* input, unsigned inputLength, URLBuffer<char>& output) = 0; -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLQueryCharsetConverter_h diff --git a/Source/WTF/wtf/url/src/RawURLBuffer.h b/Source/WTF/wtf/url/src/RawURLBuffer.h deleted file mode 100644 index e6f238c29..000000000 --- a/Source/WTF/wtf/url/src/RawURLBuffer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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" -#include <string.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/WTF/wtf/url/src/URLCanon.h b/Source/WTF/wtf/url/src/URLCanon.h deleted file mode 100644 index d1e2b1caa..000000000 --- a/Source/WTF/wtf/url/src/URLCanon.h +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 URLCanon_h -#define URLCanon_h - -#include "URLBuffer.h" -#include "URLParse.h" -#include <stdlib.h> -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -class URLQueryCharsetConverter; - -namespace URLCanonicalizer { - -// Whitespace ----------------------------------------------------------------- - -// Searches for whitespace that should be removed from the middle of URLs, and -// removes it. Removed whitespace are tabs and newlines, but NOT spaces. Spaces -// are preserved, which is what most browsers do. A pointer to the output will -// be returned, and the length of that output will be in |outputLength|. -// -// This should be called before parsing if whitespace removal is desired (which -// it normally is when you are canonicalizing). -// -// If no whitespace is removed, this function will not use the buffer and will -// return a pointer to the input, to avoid the extra copy. If modification is -// required, the given |buffer| will be used and the returned pointer will -// point to the beginning of the buffer. -// -// Therefore, callers should not use the buffer, since it may actuall be empty, -// use the computed pointer and |outputLength| instead. -const char* removeURLWhitespace(const char* input, int inputLength, URLBuffer<char>&, int& outputLength); -const UChar* removeURLWhitespace(const UChar* input, int inputLength, URLBuffer<UChar>&, int& outputLength); - -// IDN ------------------------------------------------------------------------ - -// Converts the Unicode input representing a hostname to ASCII using IDN rules. -// The output must fall in the ASCII range, but will be encoded in UTF-16. -// -// On success, the output will be filled with the ASCII host name and it will -// return true. Unlike most other canonicalization functions, this assumes that -// the output is empty. The beginning of the host will be at offset 0, and -// the length of the output will be set to the length of the new host name. -// -// On error, returns false. The output in this case is undefined. -bool IDNToASCII(const UChar* src, int sourceLength, URLBuffer<UChar>& output); - -// Piece-by-piece canonicalizers ---------------------------------------------- -// -// These individual canonicalizers append the canonicalized versions of the -// corresponding URL component to the given std::string. The spec and the -// previously-identified range of that component are the input. The range of -// the canonicalized component will be written to the output component. -// -// These functions all append to the output so they can be chained. Make sure -// the output is empty when you start. -// -// These functions returns boolean values indicating success. On failure, they -// will attempt to write something reasonable to the output so that, if -// displayed to the user, they will recognise it as something that's messed up. -// Nothing more should ever be done with these invalid URLs, however. - -// Scheme: Appends the scheme and colon to the URL. The output component will -// indicate the range of characters up to but not including the colon. -// -// Canonical URLs always have a scheme. If the scheme is not present in the -// input, this will just write the colon to indicate an empty scheme. Does not -// append slashes which will be needed before any authority components for most -// URLs. -// -// The 8-bit version requires UTF-8 encoding. -bool canonicalizeScheme(const char* spec, const URLComponent& scheme, URLBuffer<char>&, URLComponent& ouputScheme); -bool canonicalizeScheme(const UChar* spec, const URLComponent& scheme, URLBuffer<char>&, URLComponent& ouputScheme); - -// User info: username/password. If present, this will add the delimiters so -// the output will be "<username>:<password>@" or "<username>@". Empty -// username/password pairs, or empty passwords, will get converted to -// nonexistant in the canonical version. -// -// The components for the username and password refer to ranges in the -// respective source strings. Usually, these will be the same string, which -// is legal as long as the two components don't overlap. -// -// The 8-bit version requires UTF-8 encoding. -bool canonicalizeUserInfo(const char* usernameSource, const URLComponent& username, const char* passwordSource, const URLComponent& password, - URLBuffer<char>&, URLComponent& outputUsername, URLComponent& outputPassword); -bool canonicalizeUserInfo(const UChar* usernameSource, const URLComponent& username, const UChar* passwordSource, const URLComponent& password, - URLBuffer<char>&, URLComponent& outputUsername, URLComponent& outputPassword); - - -// This structure holds detailed state exported from the IP/Host canonicalizers. -// Additional fields may be added as callers require them. -struct CanonHostInfo { - CanonHostInfo() - : family(NEUTRAL) - , ipv4ComponentsCount(0) - , ouputHost() - { - } - - // Convenience function to test if family is an IP address. - bool IsIPAddress() const { return family == IPV4 || family == IPV6; } - - // This field summarizes how the input was classified by the canonicalizer. - enum Family { - // - Doesn't resemble an IP address. As far as the IP - // canonicalizer is concerned, it should be treated as a - // hostname. - NEUTRAL, - - // - Almost an IP, but was not canonicalized. This could be an - // IPv4 address where truncation occurred, or something - // containing the special characters :[] which did not parse - // as an IPv6 address. Never attempt to connect to this - // address, because it might actually succeed! - BROKEN, - - IPV4, // - Successfully canonicalized as an IPv4 address. - IPV6, // - Successfully canonicalized as an IPv6 address. - }; - Family family; - - // If |family| is IPV4, then this is the number of nonempty dot-separated - // components in the input text, from 1 to 4. If |family| is not IPV4, - // this value is undefined. - int ipv4ComponentsCount; - - // Location of host within the canonicalized output. - // canonicalizeIPAddress() only sets this field if |family| is IPV4 or IPV6. - URLComponent ouputHost; - - // |address| contains the parsed IP Address (if any) in its first - // AddressLength() bytes, in network order. If IsIPAddress() is false - // AddressLength() will return zero and the content of |address| is undefined. - unsigned char address[16]; - - // Convenience function to calculate the length of an IP address corresponding - // to the current IP version in |family|, if any. For use with |address|. - int AddressLength() const - { - return family == IPV4 ? 4 : (family == IPV6 ? 16 : 0); - } -}; - -// Host. -// -// The 8-bit version requires UTF-8 encoding. Use this version when you only -// need to know whether canonicalization succeeded. -bool canonicalizeHost(const char* spec, const URLComponent& host, URLBuffer<char>&, URLComponent& ouputHost); -bool canonicalizeHost(const UChar* spec, const URLComponent& host, URLBuffer<char>&, URLComponent& ouputHost); - -// IP addresses. -// -// Tries to interpret the given host name as an IPv4 or IPv6 address. If it is -// an IP address, it will canonicalize it as such, appending it to |output|. -// Additional status information is returned via the |*hostInfo| parameter. -// See the definition of CanonHostInfo above for details. -// -// This is called AUTOMATICALLY from the host canonicalizer, which ensures that -// the input is unescaped and name-prepped, etc. It should not normally be -// necessary or wise to call this directly. -void canonicalizeIPAddress(const char* spec, const URLComponent& host, URLBuffer<char>&, CanonHostInfo&); -void canonicalizeIPAddress(const UChar* spec, const URLComponent& host, URLBuffer<char>&, CanonHostInfo&); - -// Port: this function will add the colon for the port if a port is present. -// The caller can pass URLParser::PORT_UNSPECIFIED as the -// defaultPortForScheme argument if there is no default port. -// -// The 8-bit version requires UTF-8 encoding. -bool canonicalizePort(const char* spec, const URLComponent& port, int defaultPortForScheme, URLBuffer<char>&, URLComponent& ouputPort); -bool canonicalizePort(const UChar* spec, const URLComponent& port, int defaultPortForScheme, URLBuffer<char>&, URLComponent& ouputPort); - -// Returns the default port for the given canonical scheme, or PORT_UNSPECIFIED -// if the scheme is unknown. -int defaultPortForScheme(const char* scheme, int schemeLength); - -// Path. If the input does not begin in a slash (including if the input is -// empty), we'll prepend a slash to the path to make it canonical. -// -// The 8-bit version assumes UTF-8 encoding, but does not verify the validity -// of the UTF-8 (i.e., you can have invalid UTF-8 sequences, invalid -// characters, etc.). Normally, URLs will come in as UTF-16, so this isn't -// an issue. Somebody giving us an 8-bit path is responsible for generating -// the path that the server expects (we'll escape high-bit characters), so -// if something is invalid, it's their problem. -bool CanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); -bool CanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); - -// Canonicalizes the input as a file path. This is like CanonicalizePath except -// that it also handles Windows drive specs. For example, the path can begin -// with "c|\" and it will get properly canonicalized to "C:/". -// The string will be appended to |output| and |outputPath| will be updated. -// -// The 8-bit version requires UTF-8 encoding. -bool FileCanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); -bool FileCanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); - -// Query: Prepends the ? if needed. -// -// The 8-bit version requires the input to be UTF-8 encoding. Incorrectly -// encoded characters (in UTF-8 or UTF-16) will be replaced with the Unicode -// "invalid character." This function can not fail, we always just try to do -// our best for crazy input here since web pages can set it themselves. -// -// This will convert the given input into the output encoding that the given -// character set converter object provides. The converter will only be called -// if necessary, for ASCII input, no conversions are necessary. -// -// The converter can be null. In this case, the output encoding will be UTF-8. -void CanonicalizeQuery(const char* spec, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>&, URLComponent* outputQuery); -void CanonicalizeQuery(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>&, URLComponent* outputQuery); - -// Ref: Prepends the # if needed. The output will be UTF-8 (this is the only -// canonicalizer that does not produce ASCII output). The output is -// guaranteed to be valid UTF-8. -// -// This function will not fail. If the input is invalid UTF-8/UTF-16, we'll use -// the "Unicode replacement character" for the confusing bits and copy the rest. -void canonicalizeFragment(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent& outputFragment); -void canonicalizeFragment(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent& outputFragment); - -// Full canonicalizer --------------------------------------------------------- -// -// These functions replace any string contents, rather than append as above. -// See the above piece-by-piece functions for information specific to -// canonicalizing individual components. -// -// The output will be ASCII except the reference fragment, which may be UTF-8. -// -// The 8-bit versions require UTF-8 encoding. - -// Use for standard URLs with authorities and paths. -bool CanonicalizeStandardURL(const char* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); -bool CanonicalizeStandardURL(const UChar* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); - -// Use for file URLs. -bool CanonicalizeFileURL(const char* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); -bool CanonicalizeFileURL(const UChar* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); - -// Use for filesystem URLs. -bool canonicalizeFileSystemURL(const char* spec, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments& outputParsed); -bool canonicalizeFileSystemURL(const UChar* spec, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments& outputParsed); - -// Use for path URLs such as javascript. This does not modify the path in any -// way, for example, by escaping it. -bool canonicalizePathURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed); -bool canonicalizePathURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed); - -// Use for mailto URLs. This "canonicalizes" the url into a path and query -// component. It does not attempt to merge "to" fields. It uses UTF-8 for -// the query encoding if there is a query. This is because a mailto URL is -// really intended for an external mail program, and the encoding of a page, -// etc. which would influence a query encoding normally are irrelevant. -bool canonicalizeMailtoURL(const char* spec, const URLSegments& parsed, URLBuffer<char>&, URLSegments& outputParsed); -bool canonicalizeMailtoURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>&, URLSegments& outputParsed); - -// Part replacer -------------------------------------------------------------- - -// Internal structure used for storing separate strings for each component. -// The basic canonicalization functions use this structure internally so that -// component replacement (different strings for different components) can be -// treated on the same code path as regular canonicalization (the same string -// for each component). -// -// A URLSegments structure usually goes along with this. Those -// components identify offsets within these strings, so that they can all be -// in the same string, or spread arbitrarily across different ones. -// -// This structures does not own any data. It is the caller's responsibility to -// ensure that the data the pointers point to stays in scope and is not -// modified. -template<typename CharacterType> -struct URLComponentSource { - // Constructor normally used by callers wishing to replace components. This - // will make them all null, which is no replacement. The caller would then - // override the components they want to replace. - URLComponentSource() - : scheme(0) - , username(0) - , password(0) - , host(0) - , port(0) - , path(0) - , query(0) - , ref(0) - { - } - - // Constructor normally used internally to initialize all the components to - // point to the same spec. - explicit URLComponentSource(const CharacterType* defaultValue) - : scheme(defaultValue) - , username(defaultValue) - , password(defaultValue) - , host(defaultValue) - , port(defaultValue) - , path(defaultValue) - , query(defaultValue) - , ref(defaultValue) - { - } - - const CharacterType* scheme; - const CharacterType* username; - const CharacterType* password; - const CharacterType* host; - const CharacterType* port; - const CharacterType* path; - const CharacterType* query; - const CharacterType* ref; -}; - -// This structure encapsulates information on modifying a URL. Each component -// may either be left unchanged, replaced, or deleted. -// -// By default, each component is unchanged. For those components that should be -// modified, call either Set* or Clear* to modify it. -// -// The string passed to Set* functions DOES NOT GET COPIED AND MUST BE KEPT -// IN SCOPE BY THE CALLER for as long as this object exists! -// -// Prefer the 8-bit replacement version if possible since it is more efficient. -template<typename CharacterType> -class Replacements { -public: - Replacements() - { - } - - // Scheme - void SetScheme(const CharacterType* s, const URLComponent& comp) - { - m_sources.scheme = s; - m_segments.scheme = comp; - } - // Note: we don't have a ClearScheme since this doesn't make any sense. - bool IsSchemeOverridden() const { return !!m_sources.scheme; } - - // Username - void SetUsername(const CharacterType* s, const URLComponent& comp) - { - m_sources.username = s; - m_segments.username = comp; - } - void ClearUsername() - { - m_sources.username = Placeholder(); - m_segments.username = URLComponent(); - } - bool IsUsernameOverridden() const { return !!m_sources.username; } - - // Password - void SetPassword(const CharacterType* s, const URLComponent& comp) - { - m_sources.password = s; - m_segments.password = comp; - } - void ClearPassword() - { - m_sources.password = Placeholder(); - m_segments.password = URLComponent(); - } - bool IsPasswordOverridden() const { return !!m_sources.password; } - - // Host - void SetHost(const CharacterType* s, const URLComponent& comp) - { - m_sources.host = s; - m_segments.host = comp; - } - void ClearHost() - { - m_sources.host = Placeholder(); - m_segments.host = URLComponent(); - } - bool IsHostOverridden() const { return !!m_sources.host; } - - // Port - void SetPort(const CharacterType* s, const URLComponent& comp) - { - m_sources.port = s; - m_segments.port = comp; - } - void ClearPort() - { - m_sources.port = Placeholder(); - m_segments.port = URLComponent(); - } - bool IsPortOverridden() const { return !!m_sources.port; } - - // Path - void SetPath(const CharacterType* s, const URLComponent& comp) - { - m_sources.path = s; - m_segments.path = comp; - } - void ClearPath() - { - m_sources.path = Placeholder(); - m_segments.path = URLComponent(); - } - bool IsPathOverridden() const { return !m_sources.path; } - - // Query - void SetQuery(const CharacterType* s, const URLComponent& comp) - { - m_sources.query = s; - m_segments.query = comp; - } - void ClearQuery() - { - m_sources.query = Placeholder(); - m_segments.query = URLComponent(); - } - bool IsQueryOverridden() const { return !m_sources.query; } - - // Ref - void SetRef(const CharacterType* s, const URLComponent& comp) - { - m_sources.ref = s; - m_segments.fragment = comp; - } - void ClearRef() - { - m_sources.ref = Placeholder(); - m_segments.fragment = URLComponent(); - } - bool IsRefOverridden() const { return !m_sources.ref; } - - // Getters for the itnernal data. See the variables below for how the - // information is encoded. - const URLComponentSource<CharacterType>& sources() const { return m_sources; } - const URLSegments& components() const { return m_segments; } - -private: - // Returns a pointer to a static empty string that is used as a placeholder - // to indicate a component should be deleted (see below). - const CharacterType* Placeholder() - { - static const CharacterType emptyString = 0; - return &emptyString; - } - - // We support three states: - // - // Action | Source Component - // -----------------------+-------------------------------------------------- - // Don't change component | null (unused) - // Replace component | (replacement string) (replacement component) - // Delete component | (non-null) (invalid component: (0,-1)) - // - // We use a pointer to the empty string for the source when the component - // should be deleted. - URLComponentSource<CharacterType> m_sources; - URLSegments m_segments; -}; - -// The base must be an 8-bit canonical URL. -bool ReplaceStandardURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); -bool ReplaceStandardURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); - -// Filesystem URLs can only have the path, query, or ref replaced. -// All other components will be ignored. -bool ReplaceFileSystemURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); -bool ReplaceFileSystemURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); - -// Replacing some parts of a file URL is not permitted. Everything except -// the host, path, query, and ref will be ignored. -bool ReplaceFileURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); -bool ReplaceFileURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>&, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, - URLSegments* outputParsed); - -// Path URLs can only have the scheme and path replaced. All other components -// will be ignored. -bool ReplacePathURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>&, - URLBuffer<char>&, - URLSegments* outputParsed); -bool ReplacePathURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>&, - URLBuffer<char>&, - URLSegments* outputParsed); - -// Mailto URLs can only have the scheme, path, and query replaced. -// All other components will be ignored. -bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, - const Replacements<char>&, - URLBuffer<char>& output, URLSegments& outputParsed); -bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, - const Replacements<UChar>&, - URLBuffer<char>& output, URLSegments& outputParsed); - -// Relative URL --------------------------------------------------------------- - -// Given an input URL or URL fragment |fragment|, determines if it is a -// relative or absolute URL and places the result into |*isRelative|. If it is -// relative, the relevant portion of the URL will be placed into -// |*relativeComponent| (there may have been trimmed whitespace, for example). -// This value is passed to resolveRelativeURL. If the input is not relative, -// this value is UNDEFINED (it may be changed by the function). -// -// Returns true on success (we successfully determined the URL is relative or -// not). Failure means that the combination of URLs doesn't make any sense. -// -// The base URL should always be canonical, therefore is ASCII. -bool isRelativeURL(const char* base, const URLSegments& baseParsed, - const char* fragment, int fragmentLength, - bool isBaseHierarchical, - bool& isRelative, URLComponent& relativeComponent); -bool isRelativeURL(const char* base, const URLSegments& baseParsed, - const UChar* fragment, int fragmentLength, - bool isBaseHierarchical, - bool& isRelative, URLComponent& relativeComponent); - -// Given a canonical parsed source URL, a URL fragment known to be relative, -// and the identified relevant portion of the relative URL (computed by -// isRelativeURL), this produces a new parsed canonical URL in |output| and -// |outputParsed|. -// -// It also requires a flag indicating whether the base URL is a file: URL -// which triggers additional logic. -// -// The base URL should be canonical and have a host (may be empty for file -// URLs) and a path. If it doesn't have these, we can't resolve relative -// URLs off of it and will return the base as the output with an error flag. -// Becausee it is canonical is should also be ASCII. -// -// The query charset converter follows the same rules as CanonicalizeQuery. -// -// Returns true on success. On failure, the output will be "something -// reasonable" that will be consistent and valid, just probably not what -// was intended by the web page author or caller. -bool resolveRelativeURL(const char* baseURL, const URLSegments& baseParsed, bool baseIsFile, - const char* relativeURL, const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); -bool resolveRelativeURL(const char* baseURL, const URLSegments& baseParsed, bool baseIsFile, - const UChar* relativeURL, const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>&, URLSegments* outputParsed); - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLCanon_h diff --git a/Source/WTF/wtf/url/src/URLCanonEtc.cpp b/Source/WTF/wtf/url/src/URLCanonEtc.cpp deleted file mode 100644 index f3cdd9c97..000000000 --- a/Source/WTF/wtf/url/src/URLCanonEtc.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Canonicalizers for random bits that aren't big enough for their own files. - -#include "config.h" -#include "URLCanon.h" - -#include "URLCanonInternal.h" -#include <wtf/ASCIICType.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// Returns true if the given character should be removed from the middle of a -// URL. -inline bool isRemovableURLWhitespace(int character) -{ - return character == '\r' || character == '\n' || character == '\t'; -} - -// Backend for removeURLWhitespace (see declaration in URLCanon.h). -// It sucks that we have to do this, since this takes about 13% of the total URL -// canonicalization time. -template<typename CharacterType> -const CharacterType* doRemoveURLWhitespace(const CharacterType* input, int inputLength, URLBuffer<CharacterType>& buffer, int& outputLength) -{ - // Fast verification that there's nothing that needs removal. This is the 99% - // case, so we want it to be fast and don't care about impacting the speed - // when we do find whitespace. - bool foundWhitespace = false; - for (int i = 0; i < inputLength; ++i) { - if (!isRemovableURLWhitespace(input[i])) - continue; - foundWhitespace = true; - break; - } - - if (!foundWhitespace) { - // Didn't find any whitespace, we don't need to do anything. We can just - // return the input as the output. - outputLength = inputLength; - return input; - } - - // Remove the whitespace into the new buffer and return it. - for (int i = 0; i < inputLength; i++) { - if (!isRemovableURLWhitespace(input[i])) - buffer.append(input[i]); - } - outputLength = buffer.length(); - return buffer.data(); -} - -// Contains the canonical version of each possible input letter in the scheme -// (basically, lower-cased). The corresponding entry will be 0 if the letter -// is not allowed in a scheme. -const char kSchemeCanonical[0x80] = { -// 00-1f: all are invalid - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// ' ' ! " # $ % & ' ( ) * + , - . / - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '+', 0, '-', '.', 0, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 , 0 , 0 , 0 , 0 , 0 , -// @ A B C D E F G H I J K L M N O - 0 , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -// P Q R S T U V W X Y Z [ \ ] ^ _ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0 , 0, 0 , 0, -// ` a b c d e f g h i j k l m n o - 0 , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -// p q r s t u v w x y z { | } ~ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0 , 0 , 0 , 0 , 0 }; - -// This could be a table lookup as well by setting the high bit for each -// valid character, but it's only called once per URL, and it makes the lookup -// table easier to read not having extra stuff in it. -inline bool isSchemeFirstChar(unsigned char character) -{ - return isASCIIAlpha(character); -} - -template<typename CharacterType, typename UCHAR> -bool doScheme(const CharacterType* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) -{ - if (scheme.length() <= 0) { - // Scheme is unspecified or empty, convert to empty by appending a colon. - outputScheme = URLComponent(output.length(), 0); - output.append(':'); - return true; - } - - // The output scheme starts from the current position. - outputScheme.moveBy(output.length()); - - // Danger: it's important that this code does not strip any characters: it - // only emits the canonical version (be it valid or escaped) of each of - // the input characters. Stripping would put it out of sync with - // URLUtilities::FindAndCompareScheme, which could cause some security checks on - // schemes to be incorrect. - bool success = true; - int end = scheme.end(); - for (int i = scheme.begin(); i < end; ++i) { - UCHAR character = static_cast<UCHAR>(spec[i]); - char replacement = 0; - if (character < 0x80) { - if (i == scheme.begin()) { - // Need to do a special check for the first letter of the scheme. - if (isSchemeFirstChar(static_cast<unsigned char>(character))) - replacement = kSchemeCanonical[character]; - } else - replacement = kSchemeCanonical[character]; - } - - if (replacement) - output.append(replacement); - else if (character == '%') { - // Canonicalizing the scheme multiple times should lead to the same - // result. Since invalid characters will be escaped, we need to preserve - // the percent to avoid multiple escaping. The scheme will be invalid. - success = false; - output.append('%'); - } else { - // Invalid character, store it but mark this scheme as invalid. - success = false; - - // This will escape the output and also handle encoding issues. - // Ignore the return value since we already failed. - AppendUTF8EscapedChar(spec, &i, end, output); - } - } - - // The output scheme ends with the the current position, before appending - // the colon. - outputScheme.setLength(output.length() - outputScheme.begin()); - output.append(':'); - return success; -} - -// The username and password components reference ranges in the corresponding -// *_spec strings. Typically, these specs will be the same (we're -// canonicalizing a single source string), but may be different when -// replacing components. -template<typename CharacterType, typename UCHAR> -bool doUserInfo(const CharacterType* usernameSpec, - const URLComponent& username, - const CharacterType* passwordSpec, - const URLComponent& password, - URLBuffer<char>& output, - URLComponent& outputUsername, - URLComponent& outputPassword) -{ - if (username.length() <= 0 && password.length() <= 0) { - // Common case: no user info. We strip empty username/passwords. - outputUsername = URLComponent(); - outputPassword = URLComponent(); - return true; - } - - // Write the username. - outputUsername.setBegin(output.length()); - if (username.length() > 0) { - // This will escape characters not valid for the username. - appendStringOfType(&usernameSpec[username.begin()], username.length(), URLCharacterTypes::UserInfoCharacter, output); - } - outputUsername.setLength(output.length() - outputUsername.begin()); - - // When there is a password, we need the separator. Note that we strip - // empty but specified passwords. - if (password.length() > 0) { - output.append(':'); - outputPassword.setBegin(output.length()); - appendStringOfType(&passwordSpec[password.begin()], password.length(), URLCharacterTypes::UserInfoCharacter, output); - outputPassword.setLength(output.length() - outputPassword.begin()); - } else - outputPassword = URLComponent(); - - output.append('@'); - return true; -} - -// Helper functions for converting port integers to strings. -inline void writePortInt(char* output, int outputLength, int port) -{ - _itoa_s(port, output, outputLength, 10); -} - -// This function will prepend the colon if there will be a port. -template<typename CharacterType, typename UCHAR> -bool doPort(const CharacterType* spec, - const URLComponent& port, - int defaultPortForScheme, - URLBuffer<char>& output, - URLComponent& outputPortComponent) -{ - int portNumber = URLParser::ParsePort(spec, port); - if (portNumber == URLParser::PORT_UNSPECIFIED || portNumber == defaultPortForScheme) { - outputPortComponent = URLComponent(); - return true; // Leave port empty. - } - - if (portNumber == URLParser::PORT_INVALID) { - // Invalid port: We'll copy the text from the input so the user can see - // what the error was, and mark the URL as invalid by returning false. - output.append(':'); - outputPortComponent.setBegin(output.length()); - AppendInvalidNarrowString(spec, port.begin(), port.end(), output); - outputPortComponent.setLength(output.length() - outputPortComponent.begin()); - return false; - } - - // Convert port number back to an integer. Max port value is 5 digits, and - // the Parsed::ExtractPort will have made sure the integer is in range. - const int bufferSize = 6; - char buffer[bufferSize]; - writePortInt(buffer, bufferSize, portNumber); - - // Append the port number to the output, preceeded by a colon. - output.append(':'); - outputPortComponent.setBegin(output.length()); - for (int i = 0; i < bufferSize && buffer[i]; ++i) - output.append(buffer[i]); - - outputPortComponent.setLength(output.length() - outputPortComponent.begin()); - return true; -} - -template<typename CharacterType, typename UCHAR> -void doCanonicalizeFragment(const CharacterType* spec, const URLComponent& fragment, URLBuffer<char>& output, URLComponent& outputFragment) -{ - if (fragment.length() < 0) { - // Common case of no fragment. - outputFragment = URLComponent(); - return; - } - - // Append the fragment separator. Note that we need to do this even when the fragment - // is empty but present. - output.append('#'); - outputFragment.setBegin(output.length()); - - // Now iterate through all the characters, converting to UTF-8 and validating. - int end = fragment.end(); - for (int i = fragment.begin(); i < end; ++i) { - if (!spec[i]) { - // IE just strips NULLs, so we do too. - continue; - } - if (static_cast<UCHAR>(spec[i]) < 0x20) { - // Unline IE seems to, we escape control characters. This will probably - // make the reference fragment unusable on a web page, but people - // shouldn't be using control characters in their anchor names. - appendURLEscapedCharacter(static_cast<unsigned char>(spec[i]), output); - } else if (static_cast<UCHAR>(spec[i]) < 0x80) { - // Normal ASCII characters are just appended. - output.append(static_cast<char>(spec[i])); - } else { - // Non-ASCII characters are appended unescaped, but only when they are - // valid. Invalid Unicode characters are replaced with the "invalid - // character" as IE seems to (readUTFChar puts the unicode replacement - // character in the output on failure for us). - unsigned codePoint; - readUTFChar(spec, &i, end, &codePoint); - AppendUTF8Value(codePoint, output); - } - } - - outputFragment.setLength(output.length() - outputFragment.begin()); -} - -} // namespace - -const char* removeURLWhitespace(const char* input, int inputLength, URLBuffer<char>& buffer, int& outputLength) -{ - return doRemoveURLWhitespace(input, inputLength, buffer, outputLength); -} - -const UChar* removeURLWhitespace(const UChar* input, int inputLength, URLBuffer<UChar>& buffer, int& outputLength) -{ - return doRemoveURLWhitespace(input, inputLength, buffer, outputLength); -} - -char canonicalSchemeChar(UChar character) -{ - if (character >= 0x80) - return 0; // Non-ASCII is not supported by schemes. - return kSchemeCanonical[character]; -} - -bool canonicalizeScheme(const char* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) -{ - return doScheme<char, unsigned char>(spec, scheme, output, outputScheme); -} - -bool canonicalizeScheme(const UChar* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) -{ - return doScheme<UChar, UChar>(spec, scheme, output, outputScheme); -} - -bool canonicalizeUserInfo(const char* usernameSource, const URLComponent& username, const char* passwordSource, const URLComponent& password, - URLBuffer<char>& output, URLComponent& outputUsername, URLComponent& outputPassword) -{ - return doUserInfo<char, unsigned char>(usernameSource, username, passwordSource, password, output, outputUsername, outputPassword); -} - -bool canonicalizeUserInfo(const UChar* usernameSource, const URLComponent& username, const UChar* passwordSource, const URLComponent& password, - URLBuffer<char>& output, URLComponent& outputUsername, URLComponent& outputPassword) -{ - return doUserInfo<UChar, UChar>(usernameSource, username, passwordSource, password, output, outputUsername, outputPassword); -} - -bool canonicalizePort(const char* spec, const URLComponent& port, int defaultPortForScheme, - URLBuffer<char>& output, URLComponent& outputPortComponent) -{ - return doPort<char, unsigned char>(spec, port, - defaultPortForScheme, - output, outputPortComponent); -} - -bool canonicalizePort(const UChar* spec, const URLComponent& port, int defaultPortForScheme, - URLBuffer<char>& output, URLComponent& outputPortComponent) -{ - return doPort<UChar, UChar>(spec, port, defaultPortForScheme, - output, outputPortComponent); -} - -void canonicalizeFragment(const char* spec, const URLComponent& ref, URLBuffer<char>& output, URLComponent& outputFragment) -{ - doCanonicalizeFragment<char, unsigned char>(spec, ref, output, outputFragment); -} - -void canonicalizeFragment(const UChar* spec, const URLComponent& ref, URLBuffer<char>& output, URLComponent& outputFragment) -{ - doCanonicalizeFragment<UChar, UChar>(spec, ref, output, outputFragment); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp b/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp deleted file mode 100644 index 361bbbef7..000000000 --- a/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2012 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Functions for canonicalizing "filesystem:file:" URLs. - -#include "config.h" -#include "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" -#include "URLFile.h" -#include "URLParseInternal.h" -#include "URLUtil.h" -#include "URLUtilInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// We use the URLComponentSource for the outer URL, as it can have replacements, -// whereas the inner_url can't, so it uses spec. -template<typename CharacterType, typename UCHAR> -bool doCanonicalizeFileSystemURL(const CharacterType* spec, - const URLComponentSource<CharacterType>& source, - const URLSegments& parsed, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - // filesystem only uses {scheme, path, query, ref} -- clear the rest. - outputParsed.username = URLComponent(); - outputParsed.password = URLComponent(); - outputParsed.host = URLComponent(); - outputParsed.port = URLComponent(); - - const URLSegments* innerParsed = parsed.innerURLSegments(); - URLSegments newInnerParsed; - - // Scheme (known, so we don't bother running it through the more - // complicated scheme canonicalizer). - outputParsed.scheme.setBegin(output.length()); - output.append("filesystem:", 11); - outputParsed.scheme.setLength(10); - - if (!parsed.innerURLSegments() || !parsed.innerURLSegments()->scheme.isValid()) - return false; - - bool success = true; - if (URLUtilities::CompareSchemeComponent(spec, innerParsed->scheme, URLUtilities::kFileScheme)) { - newInnerParsed.scheme.setBegin(output.length()); - output.append("file://", 7); - newInnerParsed.scheme.setLength(4); - success &= CanonicalizePath(spec, innerParsed->path, output, - &newInnerParsed.path); - } else if (URLUtilities::isStandard(spec, innerParsed->scheme)) { - success = - URLCanonicalizer::CanonicalizeStandardURL(spec, - parsed.innerURLSegments()->length(), - *parsed.innerURLSegments(), - charsetConverter, output, - &newInnerParsed); - } else { - // TODO(ericu): The URL is wrong, but should we try to output more of what - // we were given? Echoing back filesystem:mailto etc. doesn't seem all that useful. - return false; - } - // The filesystem type must be more than just a leading slash for validity. - success &= parsed.innerURLSegments()->path.length() > 1; - - success &= CanonicalizePath(source.path, parsed.path, output, &outputParsed.path); - - // Ignore failures for query/ref since the URL can probably still be loaded. - CanonicalizeQuery(source.query, parsed.query, charsetConverter, output, &outputParsed.query); - canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); - if (success) - outputParsed.setInnerURLSegments(newInnerParsed); - - return success; -} - -} // namespace - -bool canonicalizeFileSystemURL(const char* spec, - const URLSegments& parsed, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - return doCanonicalizeFileSystemURL<char, unsigned char>(spec, URLComponentSource<char>(spec), parsed, charsetConverter, output, outputParsed); -} - -bool canonicalizeFileSystemURL(const UChar* spec, - const URLSegments& parsed, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - return doCanonicalizeFileSystemURL<UChar, UChar>(spec, URLComponentSource<UChar>(spec), parsed, charsetConverter, output, outputParsed); -} - -bool ReplaceFileSystemURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>& replacements, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupOverrideComponents(base, replacements, &source, &parsed); - return doCanonicalizeFileSystemURL<char, unsigned char>(base, source, parsed, charsetConverter, output, *outputParsed); -} - -bool ReplaceFileSystemURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>& replacements, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - RawURLBuffer<char> utf8; - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); - return doCanonicalizeFileSystemURL<char, unsigned char>(base, source, parsed, charsetConverter, output, *outputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonFileurl.cpp b/Source/WTF/wtf/url/src/URLCanonFileurl.cpp deleted file mode 100644 index 73a9f6dd1..000000000 --- a/Source/WTF/wtf/url/src/URLCanonFileurl.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Functions for canonicalizing "file:" URLs. - -#include "config.h" -#include "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" -#include "URLFile.h" -#include "URLParseInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -#if OS(WINDOWS) - -// Given a pointer into the spec, this copies and canonicalizes the drive -// letter and colon to the output, if one is found. If there is not a drive -// spec, it won't do anything. The index of the next character in the input -// spec is returned (after the colon when a drive spec is found, the begin -// offset if one is not). -template<typename CHAR> -int FileDoDriveSpec(const CHAR* spec, int begin, int end, URLBuffer<char>& output) -{ - // The path could be one of several things: /foo/bar, c:/foo/bar, /c:/foo, - // (with backslashes instead of slashes as well). - int numSlashes = URLParser::countConsecutiveSlashes(spec, begin, end); - int afterSlashes = begin + numSlashes; - - if (!URLParser::doesBeginWindowsDriveSpec(spec, afterSlashes, end)) - return begin; // Haven't consumed any characters - - // A drive spec is the start of a path, so we need to add a slash for the - // authority terminator (typically the third slash). - output.append('/'); - - // doesBeginWindowsDriveSpec will ensure that the drive letter is valid - // and that it is followed by a colon/pipe. - - // Normalize Windows drive letters to uppercase - if (spec[afterSlashes] >= 'a' && spec[afterSlashes] <= 'z') - output.append(spec[afterSlashes] - 'a' + 'A'); - else - output.append(static_cast<char>(spec[afterSlashes])); - - // Normalize the character following it to a colon rather than pipe. - output.append(':'); - return afterSlashes + 2; -} - -#endif // OS(WINDOWS) - -template<typename CharacterType, typename UCHAR> -bool doFileCanonicalizePath(const CharacterType* spec, - const URLComponent& path, - URLBuffer<char>& output, - URLComponent& outputPath) -{ - // Copies and normalizes the "c:" at the beginning, if present. - outputPath.setBegin(output.length()); - int afterDrive; -#if OS(WINDOWS) - afterDrive = FileDoDriveSpec(spec, path.begin, path.end(), output); -#else - afterDrive = path.begin(); -#endif - - // Copies the rest of the path, starting from the slash following the - // drive colon (if any, Windows only), or the first slash of the path. - bool success = true; - if (afterDrive < path.end()) { - // Use the regular path canonicalizer to canonicalize the rest of the - // path. Give it a fake output component to write into. DoCanonicalizeFile - // will compute the full path component. - URLComponent subPath = URLComponent::fromRange(afterDrive, path.end()); - URLComponent fakeOutputPath; - success = CanonicalizePath(spec, subPath, output, &fakeOutputPath); - } else { - // No input path, canonicalize to a slash. - output.append('/'); - } - - outputPath.setLength(output.length() - outputPath.begin()); - return success; -} - -template<typename CharacterType, typename UCHAR> -bool doCanonicalizeFileURL(const URLComponentSource<CharacterType>& source, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - // Things we don't set in file: URLs. - outputParsed.username = URLComponent(); - outputParsed.password = URLComponent(); - outputParsed.port = URLComponent(); - - // Scheme (known, so we don't bother running it through the more - // complicated scheme canonicalizer). - outputParsed.scheme.setBegin(output.length()); - output.append("file://", 7); - outputParsed.scheme.setLength(4); - - // Append the host. For many file URLs, this will be empty. For UNC, this - // will be present. - // TODO(brettw) This doesn't do any checking for host name validity. We - // should probably handle validity checking of UNC hosts differently than - // for regular IP hosts. - bool success = canonicalizeHost(source.host, parsed.host, output, outputParsed.host); - success &= doFileCanonicalizePath<CharacterType, UCHAR>(source.path, parsed.path, output, outputParsed.path); - CanonicalizeQuery(source.query, parsed.query, queryConverter, output, &outputParsed.query); - - // Ignore failure for refs since the URL can probably still be loaded. - canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); - - return success; -} - -} // namespace - -bool CanonicalizeFileURL(const char* spec, - int /* specLength */, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doCanonicalizeFileURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, queryConverter, output, *outputParsed); -} - -bool CanonicalizeFileURL(const UChar* spec, - int /* specLength */, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doCanonicalizeFileURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, queryConverter, output, *outputParsed); -} - -bool FileCanonicalizePath(const char* spec, - const URLComponent& path, - URLBuffer<char>& output, - URLComponent* outputPath) -{ - return doFileCanonicalizePath<char, unsigned char>(spec, path, output, *outputPath); -} - -bool FileCanonicalizePath(const UChar* spec, - const URLComponent& path, - URLBuffer<char>& output, - URLComponent* outputPath) -{ - return doFileCanonicalizePath<UChar, UChar>(spec, path, output, *outputPath); -} - -bool ReplaceFileURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>& replacements, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupOverrideComponents(base, replacements, &source, &parsed); - return doCanonicalizeFileURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); -} - -bool ReplaceFileURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>& replacements, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - RawURLBuffer<char> utf8; - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); - return doCanonicalizeFileURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonHost.cpp b/Source/WTF/wtf/url/src/URLCanonHost.cpp deleted file mode 100644 index 5ea2f9906..000000000 --- a/Source/WTF/wtf/url/src/URLCanonHost.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// For reference, here's what IE supports: -// Key: 0 (disallowed: failure if present in the input) -// + (allowed either escaped or unescaped, and unmodified) -// U (allowed escaped or unescaped but always unescaped if present in -// escaped form) -// E (allowed escaped or unescaped but always escaped if present in -// unescaped form) -// % (only allowed escaped in the input, will be unmodified). -// I left blank alpha numeric characters. -// -// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f -// ----------------------------------------------- -// 0 0 E E E E E E E E E E E E E E E -// 1 E E E E E E E E E E E E E E E E -// 2 E + E E + E + + + + + + + U U 0 -// 3 % % E + E 0 <-- Those are : ; < = > ? -// 4 % -// 5 U 0 U U U <-- Those are [ \ ] ^ _ -// 6 E <-- That's ` -// 7 E E E U E <-- Those are { | } ~ (UNPRINTABLE) -// -// NOTE: I didn't actually test all the control characters. Some may be -// disallowed in the input, but they are all accepted escaped except for 0. -// I also didn't test if characters affecting HTML parsing are allowed -// unescaped, eg. (") or (#), which would indicate the beginning of the path. -// Surprisingly, space is accepted in the input and always escaped. - -// This table lists the canonical version of all characters we allow in the -// input, with 0 indicating it is disallowed. We use the magic kEscapedHostChar -// value to indicate that this character should be escaped. We are a little more -// restrictive than IE, but less restrictive than Firefox. -// -// Note that we disallow the % character. We will allow it when part of an -// escape sequence, of course, but this disallows "%25". Even though IE allows -// it, allowing it would put us in a funny state. If there was an invalid -// escape sequence like "%zz", we'll add "%25zz" to the output and fail. -// Allowing percents means we'll succeed a second time, so validity would change -// based on how many times you run the canonicalizer. We prefer to always report -// the same vailidity, so reject this. -const unsigned char kEsc = 0xff; -const unsigned char kHostCharLookup[0x80] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// ' ' ! " # $ % & ' ( ) * + , - . / - kEsc, kEsc, kEsc, kEsc, kEsc, 0, kEsc, kEsc, kEsc, kEsc, kEsc, '+', kEsc, '-', '.', 0, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', 0 , kEsc, kEsc, kEsc, 0 , -// @ A B C D E F G H I J K L M N O - kEsc, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -// P Q R S T U V W X Y Z [ \ ] ^ _ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', 0 , ']', 0 , '_', -// ` a b c d e f g h i j k l m n o - kEsc, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', -// p q r s t u v w x y z { | } ~ - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', kEsc, kEsc, kEsc, 0 , 0 }; - -typedef RawURLBuffer<char> StackBuffer; -typedef RawURLBuffer<UChar> StackBufferW; - -// Scans a host name and fills in the output flags according to what we find. -// |hasNonASCII| will be true if there are any non-7-bit characters, and -// |hasEscaped| will be true if there is a percent sign. -template<typename CharacterType, typename UCHAR> -void scanHostname(const CharacterType* spec, const URLComponent& host, bool& hasNonASCII, bool& hasEscaped) -{ - int end = host.end(); - hasNonASCII = false; - hasEscaped = false; - for (int i = host.begin(); i < end; ++i) { - if (static_cast<UCHAR>(spec[i]) >= 0x80) - hasNonASCII = true; - else if (spec[i] == '%') - hasEscaped = true; - } -} - -// Canonicalizes a host name that is entirely 8-bit characters (even though -// the type holding them may be 16 bits. Escaped characters will be unescaped. -// Non-7-bit characters (for example, UTF-8) will be passed unchanged. -// -// The |*hasNonASCII| flag will be true if there are non-7-bit characters in -// the output. -// -// This function is used in two situations: -// -// * When the caller knows there is no non-ASCII or percent escaped -// characters. This is what DoHost does. The result will be a completely -// canonicalized host since we know nothing weird can happen (escaped -// characters could be unescaped to non-7-bit, so they have to be treated -// with suspicion at this point). It does not use the |hasNonASCII| flag. -// -// * When the caller has an 8-bit string that may need unescaping. -// doComplexHost calls us this situation to do unescaping and validation. -// After this, it may do other IDN operations depending on the value of the -// |*hasNonASCII| flag. -// -// The return value indicates if the output is a potentially valid host name. -template<typename INCHAR, typename OUTCHAR> -bool doSimpleHost(const INCHAR* host, int hostLength, URLBuffer<OUTCHAR>& output, bool& hasNonASCII) -{ - hasNonASCII = false; - - bool success = true; - for (int i = 0; i < hostLength; ++i) { - unsigned source = host[i]; - if (source == '%') { - // Unescape first, if possible. - // Source will be used only if decode operation was successful. - if (!DecodeEscaped(host, &i, hostLength, - reinterpret_cast<unsigned char*>(&source))) { - // Invalid escaped character. There is nothing that can make this - // host valid. We append an escaped percent so the URL looks reasonable - // and mark as failed. - appendURLEscapedCharacter('%', output); - success = false; - continue; - } - } - - if (source < 0x80) { - // We have ASCII input, we can use our lookup table. - unsigned char replacement = kHostCharLookup[source]; - if (!replacement) { - // Invalid character, add it as percent-escaped and mark as failed. - appendURLEscapedCharacter(source, output); - success = false; - } else if (replacement == kEsc) { - // This character is valid but should be escaped. - appendURLEscapedCharacter(source, output); - } else { - // Common case, the given character is valid in a hostname, the lookup - // table tells us the canonical representation of that character (lower - // cased). - output.append(replacement); - } - } else { - // It's a non-ascii char. Just push it to the output. - // In case where we have UChar input, and char output it's safe to - // cast UChar->char only if input string was converted to ASCII. - output.append(static_cast<OUTCHAR>(source)); - hasNonASCII = true; - } - } - - return success; -} - -// Canonicalizes a host that requires IDN conversion. Returns true on success -bool doIDNHost(const UChar* src, int sourceLength, URLBuffer<char>& output) -{ - // We need to escape URL before doing IDN conversion, since punicode strings - // cannot be escaped after they are created. - RawURLBuffer<UChar> urlEscapedHost; - bool hasNonASCII; - doSimpleHost(src, sourceLength, urlEscapedHost, hasNonASCII); - - StackBufferW wideOutput; - if (!IDNToASCII(urlEscapedHost.data(), - urlEscapedHost.length(), - wideOutput)) { - // Some error, give up. This will write some reasonable looking - // representation of the string to the output. - AppendInvalidNarrowString(src, 0, sourceLength, output); - return false; - } - - // Now we check the ASCII output like a normal host. It will also handle - // unescaping. Although we unescaped everything before this function call, if - // somebody does %00 as fullwidth, ICU will convert this to ASCII. - bool success = doSimpleHost(wideOutput.data(), wideOutput.length(), output, hasNonASCII); - ASSERT(!hasNonASCII); - return success; -} - -// 8-bit convert host to its ASCII version: this converts the UTF-8 input to -// UTF-16. The hasEscaped flag should be set if the input string requires -// unescaping. -bool doComplexHost(const char* host, int hostLength, bool hasNonASCII, bool hasEscaped, URLBuffer<char>& output) -{ - // Save the current position in the output. We may write stuff and rewind it - // below, so we need to know where to rewind to. - int beginLength = output.length(); - - // Points to the UTF-8 data we want to convert. This will either be the - // input or the unescaped version written to |output| if necessary. - const char* utf8Source; - int utf8SourceLength; - if (hasEscaped) { - // Unescape before converting to UTF-16 for IDN. We write this into the - // output because it most likely does not require IDNization, and we can - // save another huge stack buffer. It will be replaced below if it requires - // IDN. This will also update our non-ASCII flag so we know whether the - // unescaped input requires IDN. - if (!doSimpleHost(host, hostLength, output, hasNonASCII)) { - // Error with some escape sequence. We'll call the current output - // complete. doSimpleHost will have written some "reasonable" output. - return false; - } - - // Unescaping may have left us with ASCII input, in which case the - // unescaped version we wrote to output is complete. - if (!hasNonASCII) - return true; - - // Save the pointer into the data was just converted (it may be appended to - // other data in the output buffer). - utf8Source = &output.data()[beginLength]; - utf8SourceLength = output.length() - beginLength; - } else { - // We don't need to unescape, use input for IDNization later. (We know the - // input has non-ASCII, or the simple version would have been called - // instead of us.) - utf8Source = host; - utf8SourceLength = hostLength; - } - - // Non-ASCII input requires IDN, convert to UTF-16 and do the IDN conversion. - // Above, we may have used the output to write the unescaped values to, so - // we have to rewind it to where we started after we convert it to UTF-16. - StackBufferW utf16; - if (!ConvertUTF8ToUTF16(utf8Source, utf8SourceLength, utf16)) { - // In this error case, the input may or may not be the output. - StackBuffer utf8; - for (int i = 0; i < utf8SourceLength; i++) - utf8.append(utf8Source[i]); - output.setLength(beginLength); - AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output); - return false; - } - output.setLength(beginLength); - - // This will call doSimpleHost which will do normal ASCII canonicalization - // and also check for IP addresses in the outpt. - return doIDNHost(utf16.data(), utf16.length(), output); -} - -// UTF-16 convert host to its ASCII version. The set up is already ready for -// the backend, so we just pass through. The hasEscaped flag should be set if -// the input string requires unescaping. -bool doComplexHost(const UChar* host, int hostLength, bool hasNonASCII, bool hasEscaped, URLBuffer<char>& output) -{ - if (hasEscaped) { - // Yikes, we have escaped characters with wide input. The escaped - // characters should be interpreted as UTF-8. To solve this problem, - // we convert to UTF-8, unescape, then convert back to UTF-16 for IDN. - // - // We don't bother to optimize the conversion in the ASCII case (which - // *could* just be a copy) and use the UTF-8 path, because it should be - // very rare that host names have escaped characters, and it is relatively - // fast to do the conversion anyway. - StackBuffer utf8; - if (!ConvertUTF16ToUTF8(host, hostLength, utf8)) { - AppendInvalidNarrowString(host, 0, hostLength, output); - return false; - } - - // Once we convert to UTF-8, we can use the 8-bit version of the complex - // host handling code above. - return doComplexHost(utf8.data(), utf8.length(), hasNonASCII, - hasEscaped, output); - } - - // No unescaping necessary, we can safely pass the input to ICU. This - // function will only get called if we either have escaped or non-ascii - // input, so it's safe to just use ICU now. Even if the input is ASCII, - // this function will do the right thing (just slower than we could). - return doIDNHost(host, hostLength, output); -} - -template<typename CharacterType, typename UCHAR> -void doHost(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) -{ - if (host.length() <= 0) { - // Empty hosts don't need anything. - hostInfo.family = CanonHostInfo::NEUTRAL; - hostInfo.ouputHost = URLComponent(); - return; - } - - bool hasNonASCII; - bool hasEscaped; - scanHostname<CharacterType, UCHAR>(spec, host, hasNonASCII, hasEscaped); - - // Keep track of output's initial length, so we can rewind later. - const int outputBegin = output.length(); - - bool success; - if (!hasNonASCII && !hasEscaped) { - success = doSimpleHost(&spec[host.begin()], host.length(), output, hasNonASCII); - ASSERT(!hasNonASCII); - } else - success = doComplexHost(&spec[host.begin()], host.length(), hasNonASCII, hasEscaped, output); - - if (!success) { - // Canonicalization failed. Set BROKEN to notify the caller. - hostInfo.family = CanonHostInfo::BROKEN; - } else { - // After all the other canonicalization, check if we ended up with an IP - // address. IP addresses are small, so writing into this temporary buffer - // should not cause an allocation. - RawURLBuffer<char, 64> canon_ip; - canonicalizeIPAddress(output.data(), URLComponent::fromRange(outputBegin, output.length()), canon_ip, hostInfo); - - // If we got an IPv4/IPv6 address, copy the canonical form back to the - // real buffer. Otherwise, it's a hostname or broken IP, in which case - // we just leave it in place. - if (hostInfo.IsIPAddress()) { - output.setLength(outputBegin); - output.append(canon_ip.data(), canon_ip.length()); - } - } - - hostInfo.ouputHost = URLComponent::fromRange(outputBegin, output.length()); -} - -} // namespace - -bool canonicalizeHost(const char* spec, const URLComponent& host, URLBuffer<char>& output, URLComponent& ouputHost) -{ - CanonHostInfo hostInfo; - doHost<char, unsigned char>(spec, host, output, hostInfo); - ouputHost = hostInfo.ouputHost; - return (hostInfo.family != CanonHostInfo::BROKEN); -} - -bool canonicalizeHost(const UChar* spec, const URLComponent& host, URLBuffer<char>& output, URLComponent& ouputHost) -{ - CanonHostInfo hostInfo; - doHost<UChar, UChar>(spec, host, output, hostInfo); - ouputHost = hostInfo.ouputHost; - return (hostInfo.family != CanonHostInfo::BROKEN); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonICU.cpp b/Source/WTF/wtf/url/src/URLCanonICU.cpp deleted file mode 100644 index e61fa707a..000000000 --- a/Source/WTF/wtf/url/src/URLCanonICU.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2011 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// ICU integration functions. - -#include "config.h" - -#if USE(WTFURL) - -#include "URLCanonInternal.h" // for _itoa_s -#include <stdlib.h> -#include <string.h> -#include <unicode/ucnv.h> -#include <unicode/ucnv_cb.h> -#include <unicode/uidna.h> - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// Called when converting a character that can not be represented, this will -// append an escaped version of the numerical character reference for that code -// point. It is of the form "Ӓ" and we will escape the non-digits to -// "%26%231234%3B". Why? This is what Netscape did back in the olden days. -void appendURLEscapedChar(const void* /* context */, - UConverterFromUnicodeArgs* fromArgs, - const UChar* /* code_units */, - int32_t /* length */, - UChar32 codePoint, - UConverterCallbackReason reason, - UErrorCode* err) -{ - if (reason == UCNV_UNASSIGNED) { - *err = U_ZERO_ERROR; - - const static int prefixLength = 6; - const static char prefix[prefixLength + 1] = "%26%23"; // "&#" percent-escaped - ucnv_cbFromUWriteBytes(fromArgs, prefix, prefixLength, 0, err); - - ASSERT(codePoint < 0x110000); - char number[8]; // Max Unicode code point is 7 digits. - _itoa_s(codePoint, number, 10); - int numberLength = static_cast<int>(strlen(number)); - ucnv_cbFromUWriteBytes(fromArgs, number, numberLength, 0, err); - - const static int postfixLength = 3; - const static char postfix[postfixLength + 1] = "%3B"; // ";" percent-escaped - ucnv_cbFromUWriteBytes(fromArgs, postfix, postfixLength, 0, err); - } -} - -// A class for scoping the installation of the invalid character callback. -class AppendHandlerInstaller { -public: - // The owner of this object must ensure that the converter is alive for the - // duration of this object's lifetime. - AppendHandlerInstaller(UConverter* converter) - : m_converter(converter) - { - UErrorCode err = U_ZERO_ERROR; - ucnv_setFromUCallBack(m_converter, appendURLEscapedChar, 0, &m_oldCallback, &m_oldContext, &err); - } - - ~AppendHandlerInstaller() - { - UErrorCode err = U_ZERO_ERROR; - ucnv_setFromUCallBack(m_converter, m_oldCallback, m_oldContext, 0, 0, &err); - } - -private: - UConverter* m_converter; - - UConverterFromUCallback m_oldCallback; - const void* m_oldContext; -}; - -} // namespace - -// Converts the Unicode input representing a hostname to ASCII using IDN rules. -// The output must be ASCII, but is represented as wide characters. -// -// On success, the output will be filled with the ASCII host name and it will -// return true. Unlike most other canonicalization functions, this assumes that -// the output is empty. The beginning of the host will be at offset 0, and -// the length of the output will be set to the length of the new host name. -// -// On error, this will return false. The output in this case is undefined. -bool IDNToASCII(const UChar* src, int sourceLength, URLBuffer<UChar>& output) -{ - ASSERT(!output.length()); // Output buffer is assumed empty. - while (true) { - // Use ALLOW_UNASSIGNED to be more tolerant of hostnames that violate - // the spec (which do exist). This does not present any risk and is a - // little more future proof. - UErrorCode err = U_ZERO_ERROR; - int numConverted = uidna_IDNToASCII(src, sourceLength, output.data(), - output.capacity(), - UIDNA_ALLOW_UNASSIGNED, 0, &err); - if (err == U_ZERO_ERROR) { - output.setLength(numConverted); - return true; - } - if (err != U_BUFFER_OVERFLOW_ERROR) - return false; // Unknown error, give up. - - // Not enough room in our buffer, expand. - output.resize(output.capacity() * 2); - } -} - -bool readUTFChar(const char* str, int* begin, int length, unsigned* codePointOut) -{ - int codePoint; // Avoids warning when U8_NEXT writes -1 to it. - U8_NEXT(str, *begin, length, codePoint); - *codePointOut = static_cast<unsigned>(codePoint); - - // The ICU macro above moves to the next char, we want to point to the last - // char consumed. - (*begin)--; - - // Validate the decoded value. - if (U_IS_UNICODE_CHAR(codePoint)) - return true; - *codePointOut = kUnicodeReplacementCharacter; - return false; -} - -bool readUTFChar(const UChar* str, int* begin, int length, unsigned* codePoint) -{ - if (U16_IS_SURROGATE(str[*begin])) { - if (!U16_IS_SURROGATE_LEAD(str[*begin]) || *begin + 1 >= length || !U16_IS_TRAIL(str[*begin + 1])) { - // Invalid surrogate pair. - *codePoint = kUnicodeReplacementCharacter; - return false; - } - - // Valid surrogate pair. - *codePoint = U16_GET_SUPPLEMENTARY(str[*begin], str[*begin + 1]); - (*begin)++; - } else { - // Not a surrogate, just one 16-bit word. - *codePoint = str[*begin]; - } - - if (U_IS_UNICODE_CHAR(*codePoint)) - return true; - - // Invalid code point. - *codePoint = kUnicodeReplacementCharacter; - return false; -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonIP.cpp b/Source/WTF/wtf/url/src/URLCanonIP.cpp deleted file mode 100644 index 4462353cb..000000000 --- a/Source/WTF/wtf/url/src/URLCanonIP.cpp +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright 2009 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLCanonInternal.h" -#include "URLCharacterTypes.h" -#include <limits> -#include <stdint.h> -#include <stdlib.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// Converts one of the character types that represent a numerical base to the -// corresponding base. -static inline int baseForType(URLCharacterTypes::CharacterTypes type) -{ - switch (type) { - case URLCharacterTypes::HexadecimalCharacter: - return 16; - case URLCharacterTypes::DecimalCharacter: - return 10; - case URLCharacterTypes::OctalCharacter: - return 8; - default: - return 0; - } -} - -// Converts an IPv4 component to a 32-bit number, while checking for overflow. -// -// Possible return values: -// - IPV4 - The number was valid, and did not overflow. -// - BROKEN - The input was numeric, but too large for a 32-bit field. -// - NEUTRAL - Input was not numeric. -// -// The input is assumed to be ASCII. FindIPv4Components should have stripped -// out any input that is greater than 7 bits. The components are assumed -// to be non-empty. -template<typename CharacterType> -CanonHostInfo::Family IPv4ComponentToNumber(const CharacterType* spec, const URLComponent& component, uint32_t* number) -{ - // Figure out the base - URLCharacterTypes::CharacterTypes base; - int basePrefixLength = 0; // Size of the prefix for this base. - if (spec[component.begin()] == '0') { - // Either hex or dec, or a standalone zero. - if (component.length() == 1) { - base = URLCharacterTypes::DecimalCharacter; - } else if (spec[component.begin() + 1] == 'X' || spec[component.begin() + 1] == 'x') { - base = URLCharacterTypes::HexadecimalCharacter; - basePrefixLength = 2; - } else { - base = URLCharacterTypes::OctalCharacter; - basePrefixLength = 1; - } - } else - base = URLCharacterTypes::DecimalCharacter; - - // Extend the prefix to consume all leading zeros. - while (basePrefixLength < component.length() && spec[component.begin() + basePrefixLength] == '0') - ++basePrefixLength; - - // Put the component, minus any base prefix, into a zero-terminated buffer so - // we can call the standard library. Because leading zeros have already been - // discarded, filling the entire buffer is guaranteed to trigger the 32-bit - // overflow check. - const int kMaxComponentLen = 16; - char buf[kMaxComponentLen + 1]; // digits + '\0' - int destI = 0; - for (int i = component.begin() + basePrefixLength; i < component.end(); i++) { - // We know the input is 7-bit, so convert to narrow (if this is the wide - // version of the template) by casting. - char input = static_cast<char>(spec[i]); - - // Validate that this character is OK for the given base. - if (!URLCharacterTypes::isCharacterOfType(input, base)) - return CanonHostInfo::NEUTRAL; - - // Fill the buffer, if there's space remaining. This check allows us to - // verify that all characters are numeric, even those that don't fit. - if (destI < kMaxComponentLen) - buf[destI++] = input; - } - - buf[destI] = '\0'; - - // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal - // number can overflow a 64-bit number in <= 16 characters). - uint64_t num = _strtoui64(buf, 0, baseForType(base)); - - // Check for 32-bit overflow. - if (num > std::numeric_limits<uint32_t>::max()) - return CanonHostInfo::BROKEN; - - // No overflow. Success! - *number = static_cast<uint32_t>(num); - return CanonHostInfo::IPV4; -} - -template<typename CharacterType, typename UCHAR> -bool doFindIPv4Components(const CharacterType* spec, const URLComponent& host, URLComponent components[4]) -{ - if (!host.isNonEmpty()) - return false; - - int currentComponent = 0; // Index of the component we're working on. - int currentComponentBegin = host.begin(); // Start of the current component. - int end = host.end(); - for (int i = host.begin(); /* nothing */; ++i) { - if (i >= end || spec[i] == '.') { - // Found the end of the current component. - int componentLength = i - currentComponentBegin; - components[currentComponent] = URLComponent(currentComponentBegin, componentLength); - - // The next component starts after the dot. - currentComponentBegin = i + 1; - currentComponent++; - - // Don't allow empty components (two dots in a row), except we may - // allow an empty component at the end (this would indicate that the - // input ends in a dot). We also want to error if the component is - // empty and it's the only component (currentComponent == 1). - if (!componentLength && (i < end || currentComponent == 1)) - return false; - - if (i >= end) - break; // End of the input. - - if (currentComponent == 4) { - // Anything else after the 4th component is an error unless it is a - // dot that would otherwise be treated as the end of input. - if (spec[i] == '.' && i + 1 == end) - break; - return false; - } - } else if (static_cast<UCHAR>(spec[i]) >= 0x80 || !URLCharacterTypes::isIPv4Char(static_cast<unsigned char>(spec[i]))) { - // Invalid character for an IPv4 address. - return false; - } - } - - // Fill in any unused components. - while (currentComponent < 4) - components[currentComponent++] = URLComponent(); - return true; -} - -static bool FindIPv4Components(const char* spec, const URLComponent& host, URLComponent components[4]) -{ - return doFindIPv4Components<char, unsigned char>(spec, host, components); -} - -static bool FindIPv4Components(const UChar* spec, const URLComponent& host, URLComponent components[4]) -{ - return doFindIPv4Components<UChar, UChar>(spec, host, components); -} - -template<typename CharacterType> -CanonHostInfo::Family doIPv4AddressToNumber(const CharacterType* spec, const URLComponent& host, unsigned char address[4], int& ipv4ComponentsCount) -{ - // The identified components. Not all may exist. - URLComponent components[4]; - if (!FindIPv4Components(spec, host, components)) - return CanonHostInfo::NEUTRAL; - - // Convert existing components to digits. Values up to - // |existingComponents| will be valid. - uint32_t componentValues[4]; - int existingComponents = 0; - - // Set to true if one or more components are BROKEN. BROKEN is only - // returned if all components are IPV4 or BROKEN, so, for example, - // 12345678912345.de returns NEUTRAL rather than broken. - bool broken = false; - for (int i = 0; i < 4; i++) { - if (components[i].length() <= 0) - continue; - CanonHostInfo::Family family = IPv4ComponentToNumber(spec, components[i], &componentValues[existingComponents]); - - if (family == CanonHostInfo::BROKEN) - broken = true; - else if (family != CanonHostInfo::IPV4) { - // Stop if we hit a non-BROKEN invalid non-empty component. - return family; - } - - existingComponents++; - } - - if (broken) - return CanonHostInfo::BROKEN; - - // Use that sequence of numbers to fill out the 4-component IP address. - - // First, process all components but the last, while making sure each fits - // within an 8-bit field. - for (int i = 0; i < existingComponents - 1; i++) { - if (componentValues[i] > std::numeric_limits<uint8_t>::max()) - return CanonHostInfo::BROKEN; - address[i] = static_cast<unsigned char>(componentValues[i]); - } - - // Next, consume the last component to fill in the remaining bytes. - uint32_t lastValue = componentValues[existingComponents - 1]; - for (int i = 3; i >= existingComponents - 1; i--) { - address[i] = static_cast<unsigned char>(lastValue); - lastValue >>= 8; - } - - // If the last component has residual bits, report overflow. - if (lastValue) - return CanonHostInfo::BROKEN; - - // Tell the caller how many components we saw. - ipv4ComponentsCount = existingComponents; - - // Success! - return CanonHostInfo::IPV4; -} - -static inline void appendIPv4Address(const unsigned char address[4], URLBuffer<char>& output) -{ - for (int i = 0; i < 4; ++i) { - char buffer[16]; - _itoa_s(address[i], buffer, 10); - - for (int ch = 0; buffer[ch]; ch++) - output.append(buffer[ch]); - - if (i != 3) - output.append('.'); - } -} - -// Return true if we've made a final IPV4/BROKEN decision, false if the result -// is NEUTRAL, and we could use a second opinion. -template<typename CharacterType, typename UCHAR> -bool doCanonicalizeIPv4Address(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) -{ - hostInfo.family = doIPv4AddressToNumber(spec, host, hostInfo.address, hostInfo.ipv4ComponentsCount); - - switch (hostInfo.family) { - case CanonHostInfo::IPV4: - // Definitely an IPv4 address. - hostInfo.ouputHost.setBegin(output.length()); - appendIPv4Address(hostInfo.address, output); - hostInfo.ouputHost.setLength(output.length() - hostInfo.ouputHost.begin()); - return true; - case CanonHostInfo::BROKEN: - // Definitely broken. - return true; - default: - // Could be IPv6 or a hostname. - return false; - } -} - -// Helper class that describes the main components of an IPv6 input string. -// See the following examples to understand how it breaks up an input string: -// -// [Example 1]: input = "[::aa:bb]" -// ==> numHexComponents = 2 -// ==> hexComponents[0] = Component(3,2) "aa" -// ==> hexComponents[1] = Component(6,2) "bb" -// ==> indexOfContraction = 0 -// ==> ipv4Component = Component(0, -1) -// -// [Example 2]: input = "[1:2::3:4:5]" -// ==> numHexComponents = 5 -// ==> hexComponents[0] = Component(1,1) "1" -// ==> hexComponents[1] = Component(3,1) "2" -// ==> hexComponents[2] = Component(6,1) "3" -// ==> hexComponents[3] = Component(8,1) "4" -// ==> hexComponents[4] = Component(10,1) "5" -// ==> indexOfContraction = 2 -// ==> ipv4Component = Component(0, -1) -// -// [Example 3]: input = "[::ffff:192.168.0.1]" -// ==> numHexComponents = 1 -// ==> hexComponents[0] = Component(3,4) "ffff" -// ==> indexOfContraction = 0 -// ==> ipv4Component = Component(8, 11) "192.168.0.1" -// -// [Example 4]: input = "[1::]" -// ==> numHexComponents = 1 -// ==> hexComponents[0] = Component(1,1) "1" -// ==> indexOfContraction = 1 -// ==> ipv4Component = Component(0, -1) -// -// [Example 5]: input = "[::192.168.0.1]" -// ==> numHexComponents = 0 -// ==> indexOfContraction = 0 -// ==> ipv4Component = Component(8, 11) "192.168.0.1" -// -struct IPv6Parsed { - // Zero-out the parse information. - void reset() - { - numHexComponents = 0; - indexOfContraction = -1; - ipv4Component.reset(); - } - - // There can be up to 8 hex components (colon separated) in the literal. - URLComponent hexComponents[8]; - - // The count of hex components present. Ranges from [0,8]. - int numHexComponents; - - // The index of the hex component that the "::" contraction precedes, or - // -1 if there is no contraction. - int indexOfContraction; - - // The range of characters which are an IPv4 literal. - URLComponent ipv4Component; -}; - -// Parse the IPv6 input string. If parsing succeeded returns true and fills -// |parsed| with the information. If parsing failed (because the input is -// invalid) returns false. -template<typename CharacterType, typename UCHAR> -bool doParseIPv6(const CharacterType* spec, const URLComponent& host, IPv6Parsed& parsed) -{ - // Zero-out the info. - parsed.reset(); - - if (!host.isNonEmpty()) - return false; - - // The index for start and end of address range (no brackets). - int begin = host.begin(); - int end = host.end(); - - int currentComponentBegin = begin; // Start of the current component. - - // Scan through the input, searching for hex components, "::" contractions, - // and IPv4 components. - for (int i = begin; /* i <= end */; i++) { - bool isColon = spec[i] == ':'; - bool isContraction = isColon && i < end - 1 && spec[i + 1] == ':'; - - // We reached the end of the current component if we encounter a colon - // (separator between hex components, or start of a contraction), or end of - // input. - if (isColon || i == end) { - int componentLength = i - currentComponentBegin; - - // A component should not have more than 4 hex digits. - if (componentLength > 4) - return false; - - // Don't allow empty components. - if (!componentLength) { - // The exception is when contractions appear at beginning of the - // input or at the end of the input. - if (!((isContraction && i == begin) || (i == end && parsed.indexOfContraction == parsed.numHexComponents))) - return false; - } - - // Add the hex component we just found to running list. - if (componentLength > 0) { - // Can't have more than 8 components! - if (parsed.numHexComponents >= 8) - return false; - - parsed.hexComponents[parsed.numHexComponents++] = - URLComponent(currentComponentBegin, componentLength); - } - } - - if (i == end) - break; // Reached the end of the input, DONE. - - // We found a "::" contraction. - if (isContraction) { - // There can be at most one contraction in the literal. - if (parsed.indexOfContraction != -1) - return false; - parsed.indexOfContraction = parsed.numHexComponents; - ++i; // Consume the colon we peeked. - } - - if (isColon) { - // Colons are separators between components, keep track of where the - // current component started (after this colon). - currentComponentBegin = i + 1; - } else { - if (static_cast<UCHAR>(spec[i]) >= 0x80) - return false; // Not ASCII. - - if (!URLCharacterTypes::isHexChar(static_cast<unsigned char>(spec[i]))) { - // Regular components are hex numbers. It is also possible for - // a component to be an IPv4 address in dotted form. - if (URLCharacterTypes::isIPv4Char(static_cast<unsigned char>(spec[i]))) { - // Since IPv4 address can only appear at the end, assume the rest - // of the string is an IPv4 address. (We will parse this separately - // later). - parsed.ipv4Component = URLComponent::fromRange(currentComponentBegin, end); - break; - } - // The character was neither a hex digit, nor an IPv4 character. - return false; - } - } - } - - return true; -} - -// Verifies the parsed IPv6 information, checking that the various components -// add up to the right number of bits (hex components are 16 bits, while -// embedded IPv4 formats are 32 bits, and contractions are placeholdes for -// 16 or more bits). Returns true if sizes match up, false otherwise. On -// success writes the length of the contraction (if any) to -// |outNumBytesOfContraction|. -bool CheckIPv6ComponentsSize(const IPv6Parsed& parsed, int* outNumBytesOfContraction) -{ - // Each group of four hex digits contributes 16 bits. - int numBytesWithoutContraction = parsed.numHexComponents * 2; - - // If an IPv4 address was embedded at the end, it contributes 32 bits. - if (parsed.ipv4Component.isValid()) - numBytesWithoutContraction += 4; - - // If there was a "::" contraction, its size is going to be: - // MAX([16bits], [128bits] - numBytesWithoutContraction). - int numBytesOfContraction = 0; - if (parsed.indexOfContraction != -1) { - numBytesOfContraction = 16 - numBytesWithoutContraction; - if (numBytesOfContraction < 2) - numBytesOfContraction = 2; - } - - // Check that the numbers add up. - if (numBytesWithoutContraction + numBytesOfContraction != 16) - return false; - - *outNumBytesOfContraction = numBytesOfContraction; - return true; -} - -// Converts a hex comonent into a number. This cannot fail since the caller has -// already verified that each character in the string was a hex digit, and -// that there were no more than 4 characters. -template<typename CharacterType> -uint16_t IPv6HexComponentToNumber(const CharacterType* spec, const URLComponent& component) -{ - ASSERT(component.length() <= 4); - - // Copy the hex string into a C-string. - char buf[5]; - for (int i = 0; i < component.length(); ++i) - buf[i] = static_cast<char>(spec[component.begin() + i]); - buf[component.length()] = '\0'; - - // Convert it to a number (overflow is not possible, since with 4 hex - // characters we can at most have a 16 bit number). - return static_cast<uint16_t>(_strtoui64(buf, 0, 16)); -} - -// Converts an IPv6 address to a 128-bit number (network byte order), returning -// true on success. False means that the input was not a valid IPv6 address. -template<typename CharacterType, typename UCHAR> -bool doIPv6AddressToNumber(const CharacterType* spec, - const URLComponent& host, - unsigned char address[16]) -{ - // Make sure the component is bounded by '[' and ']'. - int end = host.end(); - if (!host.isNonEmpty() || spec[host.begin()] != '[' || spec[end - 1] != ']') - return false; - - // Exclude the square brackets. - URLComponent ipv6Component(host.begin() + 1, host.length() - 2); - - // Parse the IPv6 address -- identify where all the colon separated hex - // components are, the "::" contraction, and the embedded IPv4 address. - IPv6Parsed ipv6Parsed; - if (!doParseIPv6<CharacterType, UCHAR>(spec, ipv6Component, ipv6Parsed)) - return false; - - // Do some basic size checks to make sure that the address doesn't - // specify more than 128 bits or fewer than 128 bits. This also resolves - // how may zero bytes the "::" contraction represents. - int numBytesOfContraction; - if (!CheckIPv6ComponentsSize(ipv6Parsed, &numBytesOfContraction)) - return false; - - int currentIndexInAddress = 0; - - // Loop through each hex components, and contraction in order. - for (int i = 0; i <= ipv6Parsed.numHexComponents; ++i) { - // Append the contraction if it appears before this component. - if (i == ipv6Parsed.indexOfContraction) { - for (int j = 0; j < numBytesOfContraction; ++j) - address[currentIndexInAddress++] = 0; - } - // Append the hex component's value. - if (i != ipv6Parsed.numHexComponents) { - // Get the 16-bit value for this hex component. - uint16_t number = IPv6HexComponentToNumber<CharacterType>(spec, ipv6Parsed.hexComponents[i]); - // Append to |address|, in network byte order. - address[currentIndexInAddress++] = (number & 0xFF00) >> 8; - address[currentIndexInAddress++] = (number & 0x00FF); - } - } - - // If there was an IPv4 section, convert it into a 32-bit number and append - // it to |address|. - if (ipv6Parsed.ipv4Component.isValid()) { - // Append the 32-bit number to |address|. - int ignoredIPv4ComponentsCount; - if (CanonHostInfo::IPV4 != - doIPv4AddressToNumber(spec, ipv6Parsed.ipv4Component, &address[currentIndexInAddress], ignoredIPv4ComponentsCount)) - return false; - } - - return true; -} - -// Searches for the longest sequence of zeros in |address|, and writes the -// range into |contractionRange|. The run of zeros must be at least 16 bits, -// and if there is a tie the first is chosen. -void ChooseIPv6ContractionRange(const unsigned char address[16], URLComponent* contractionRange) -{ - // The longest run of zeros in |address| seen so far. - URLComponent maxRange; - - // The current run of zeros in |address| being iterated over. - URLComponent currentRange; - - for (int i = 0; i < 16; i += 2) { - // Test for 16 bits worth of zero. - bool isZero = (!address[i] && !address[i + 1]); - - if (isZero) { - // Add the zero to the current range (or start a new one). - if (!currentRange.isValid()) - currentRange = URLComponent(i, 0); - currentRange.setLength(currentRange.length() + 2); - } - - if (!isZero || i == 14) { - // Just completed a run of zeros. If the run is greater than 16 bits, - // it is a candidate for the contraction. - if (currentRange.length() > 2 && currentRange.length() > maxRange.length()) - maxRange = currentRange; - - currentRange.reset(); - } - } - *contractionRange = maxRange; -} - -static inline void appendIPv6Address(const unsigned char address[16], URLBuffer<char>& output) -{ - // We will output the address according to the rules in: - // http://tools.ietf.org/html/draft-kawamura-ipv6-text-representation-01#section-4 - - // Start by finding where to place the "::" contraction (if any). - URLComponent contractionRange; - ChooseIPv6ContractionRange(address, &contractionRange); - - for (int i = 0; i <= 14;) { - // We check 2 bytes at a time, from bytes (0, 1) to (14, 15), inclusive. - ASSERT(!(i % 2)); - if (i == contractionRange.begin() && contractionRange.length() > 0) { - // Jump over the contraction. - if (!i) - output.append(':'); - output.append(':'); - i = contractionRange.end(); - } else { - // Consume the next 16 bits from |address|. - int x = address[i] << 8 | address[i + 1]; - - i += 2; - - // Stringify the 16 bit number (at most requires 4 hex digits). - char str[5]; - _itoa_s(x, str, 16); - for (int ch = 0; str[ch]; ++ch) - output.append(str[ch]); - - // Put a colon after each number, except the last. - if (i < 16) - output.append(':'); - } - } -} - -// Return true if we've made a final IPV6/BROKEN decision, false if the result -// is NEUTRAL, and we could use a second opinion. -template<typename CharacterType, typename UCHAR> -bool doCanonicalizeIPv6Address(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) -{ - // Turn the IP address into a 128 bit number. - if (!doIPv6AddressToNumber<CharacterType, UCHAR>(spec, host, hostInfo.address)) { - // If it's not an IPv6 address, scan for characters that should *only* - // exist in an IPv6 address. - for (int i = host.begin(); i < host.end(); i++) { - switch (spec[i]) { - case '[': - case ']': - case ':': - hostInfo.family = CanonHostInfo::BROKEN; - return true; - } - } - - // No invalid characters. Could still be IPv4 or a hostname. - hostInfo.family = CanonHostInfo::NEUTRAL; - return false; - } - - hostInfo.ouputHost.setBegin(output.length()); - output.append('['); - appendIPv6Address(hostInfo.address, output); - output.append(']'); - hostInfo.ouputHost.setLength(output.length() - hostInfo.ouputHost.begin()); - - hostInfo.family = CanonHostInfo::IPV6; - return true; -} - -} // namespace - -void canonicalizeIPAddress(const char* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) -{ - if (doCanonicalizeIPv4Address<char, unsigned char>(spec, host, output, hostInfo)) - return; - if (doCanonicalizeIPv6Address<char, unsigned char>(spec, host, output, hostInfo)) - return; -} - -void canonicalizeIPAddress(const UChar* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) -{ - if (doCanonicalizeIPv4Address<UChar, UChar>(spec, host, output, hostInfo)) - return; - if (doCanonicalizeIPv6Address<UChar, UChar>(spec, host, output, hostInfo)) - return; -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonInternal.cpp b/Source/WTF/wtf/url/src/URLCanonInternal.cpp deleted file mode 100644 index b7ae09814..000000000 --- a/Source/WTF/wtf/url/src/URLCanonInternal.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLCanonInternal.h" - -#include <cstdio> -#include <errno.h> -#include <stdlib.h> -#include <string> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -template<typename CharacterType, typename UCHAR> -void doAppendStringOfType(const CharacterType* source, int length, URLCharacterTypes::CharacterTypes type, URLBuffer<char>& output) -{ - for (int i = 0; i < length; ++i) { - if (static_cast<UCHAR>(source[i]) >= 0x80) { - // ReadChar will fill the code point with kUnicodeReplacementCharacter - // when the input is invalid, which is what we want. - unsigned codePoint; - readUTFChar(source, &i, length, &codePoint); - AppendUTF8EscapedValue(codePoint, output); - } else { - // Just append the 7-bit character, possibly escaping it. - unsigned char uch = static_cast<unsigned char>(source[i]); - if (!URLCharacterTypes::isCharacterOfType(uch, type)) - appendURLEscapedCharacter(uch, output); - else - output.append(uch); - } - } -} - -// This function assumes the input values are all contained in 8-bit, -// although it allows any type. Returns true if input is valid, false if not. -template<typename CharacterType, typename UCHAR> -void doAppendInvalidNarrowString(const CharacterType* spec, int begin, int end, URLBuffer<char>& output) -{ - for (int i = begin; i < end; ++i) { - UCHAR uch = static_cast<UCHAR>(spec[i]); - if (uch >= 0x80) { - // Handle UTF-8/16 encodings. This call will correctly handle the error - // case by appending the invalid character. - AppendUTF8EscapedChar(spec, &i, end, output); - } else if (uch <= ' ' || uch == 0x7f) { - // This function is for error handling, so we escape all control - // characters and spaces, but not anything else since we lack - // context to do something more specific. - appendURLEscapedCharacter(static_cast<unsigned char>(uch), output); - } else - output.append(static_cast<char>(uch)); - } -} - -// Overrides one component, see the URLCanonicalizer::Replacements structure for -// what the various combionations of source pointer and component mean. -void doOverrideComponent(const char* overrideSource, const URLComponent& overrideComponent, const char*& destination, URLComponent& destinationComponent) -{ - if (overrideSource) { - destination = overrideSource; - destinationComponent = overrideComponent; - } -} - -// Similar to doOverrideComponent except that it takes a UTF-16 input and does -// not actually set the output character pointer. -// -// The input is converted to UTF-8 at the end of the given buffer as a temporary -// holding place. The component indentifying the portion of the buffer used in -// the |utf8Buffer| will be specified in |*destinationComponent|. -// -// This will not actually set any |dest| pointer like doOverrideComponent -// does because all of the pointers will point into the |utf8Buffer|, which -// may get resized while we're overriding a subsequent component. Instead, the -// caller should use the beginning of the |utf8Buffer| as the string pointer -// for all components once all overrides have been prepared. -bool PrepareUTF16OverrideComponent(const UChar* overrideSource, - const URLComponent& overrideComponent, - URLBuffer<char>& utf8Buffer, - URLComponent* destinationComponent) -{ - bool success = true; - if (overrideSource) { - if (!overrideComponent.isValid()) { - // Non-"valid" component (means delete), so we need to preserve that. - *destinationComponent = URLComponent(); - } else { - // Convert to UTF-8. - destinationComponent->setBegin(utf8Buffer.length()); - success = ConvertUTF16ToUTF8(&overrideSource[overrideComponent.begin()], - overrideComponent.length(), utf8Buffer); - destinationComponent->setLength(utf8Buffer.length() - destinationComponent->begin()); - } - } - return success; -} - -} // namespace - -const char kCharToHexLookup[8] = { - 0, // 0x00 - 0x1f - '0', // 0x20 - 0x3f: digits 0 - 9 are 0x30 - 0x39 - 'A' - 10, // 0x40 - 0x5f: letters A - F are 0x41 - 0x46 - 'a' - 10, // 0x60 - 0x7f: letters a - f are 0x61 - 0x66 - 0, // 0x80 - 0x9F - 0, // 0xA0 - 0xBF - 0, // 0xC0 - 0xDF - 0, // 0xE0 - 0xFF -}; - -const UChar kUnicodeReplacementCharacter = 0xfffd; - -void appendStringOfType(const char* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output) -{ - doAppendStringOfType<char, unsigned char>(source, length, urlComponentType, output); -} - -void appendStringOfType(const UChar* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output) -{ - doAppendStringOfType<UChar, UChar>(source, length, urlComponentType, output); -} - -void AppendInvalidNarrowString(const char* spec, int begin, int end, URLBuffer<char>& output) -{ - doAppendInvalidNarrowString<char, unsigned char>(spec, begin, end, output); -} - -void AppendInvalidNarrowString(const UChar* spec, int begin, int end, URLBuffer<char>& output) -{ - doAppendInvalidNarrowString<UChar, UChar>(spec, begin, end, output); -} - -bool ConvertUTF16ToUTF8(const UChar* input, int inputLength, URLBuffer<char>& output) -{ - bool success = true; - for (int i = 0; i < inputLength; ++i) { - unsigned codePoint; - success &= readUTFChar(input, &i, inputLength, &codePoint); - AppendUTF8Value(codePoint, output); - } - return success; -} - -bool ConvertUTF8ToUTF16(const char* input, int inputLength, URLBuffer<UChar>& output) -{ - bool success = true; - for (int i = 0; i < inputLength; i++) { - unsigned codePoint; - success &= readUTFChar(input, &i, inputLength, &codePoint); - AppendUTF16Value(codePoint, output); - } - return success; -} - -void SetupOverrideComponents(const char* /* base */, - const Replacements<char>& repl, - URLComponentSource<char>* source, - URLSegments* parsed) -{ - // Get the source and parsed structures of the things we are replacing. - const URLComponentSource<char>& replSource = repl.sources(); - const URLSegments& replParsed = repl.components(); - - doOverrideComponent(replSource.scheme, replParsed.scheme, source->scheme, parsed->scheme); - doOverrideComponent(replSource.username, replParsed.username, source->username, parsed->username); - doOverrideComponent(replSource.password, replParsed.password, source->password, parsed->password); - - // Our host should be empty if not present, so override the default setup. - doOverrideComponent(replSource.host, replParsed.host, source->host, parsed->host); - if (parsed->host.length() == -1) - parsed->host.setLength(0); - - doOverrideComponent(replSource.port, replParsed.port, source->port, parsed->port); - doOverrideComponent(replSource.path, replParsed.path, source->path, parsed->path); - doOverrideComponent(replSource.query, replParsed.query, source->query, parsed->query); - doOverrideComponent(replSource.ref, replParsed.fragment, source->ref, parsed->fragment); -} - -bool SetupUTF16OverrideComponents(const char* /* base */, - const Replacements<UChar>& repl, - URLBuffer<char>& utf8Buffer, - URLComponentSource<char>* source, - URLSegments* parsed) - { - bool success = true; - - // Get the source and parsed structures of the things we are replacing. - const URLComponentSource<UChar>& replSource = repl.sources(); - const URLSegments& replParsed = repl.components(); - - success &= PrepareUTF16OverrideComponent(replSource.scheme, replParsed.scheme, - utf8Buffer, &parsed->scheme); - success &= PrepareUTF16OverrideComponent(replSource.username, replParsed.username, - utf8Buffer, &parsed->username); - success &= PrepareUTF16OverrideComponent(replSource.password, replParsed.password, - utf8Buffer, &parsed->password); - success &= PrepareUTF16OverrideComponent(replSource.host, replParsed.host, - utf8Buffer, &parsed->host); - success &= PrepareUTF16OverrideComponent(replSource.port, replParsed.port, - utf8Buffer, &parsed->port); - success &= PrepareUTF16OverrideComponent(replSource.path, replParsed.path, - utf8Buffer, &parsed->path); - success &= PrepareUTF16OverrideComponent(replSource.query, replParsed.query, - utf8Buffer, &parsed->query); - success &= PrepareUTF16OverrideComponent(replSource.ref, replParsed.fragment, - utf8Buffer, &parsed->fragment); - - // PrepareUTF16OverrideComponent will not have set the data pointer since the - // buffer could be resized, invalidating the pointers. We set the data - // pointers for affected components now that the buffer is finalized. - if (replSource.scheme) - source->scheme = utf8Buffer.data(); - if (replSource.username) - source->username = utf8Buffer.data(); - if (replSource.password) - source->password = utf8Buffer.data(); - if (replSource.host) - source->host = utf8Buffer.data(); - if (replSource.port) - source->port = utf8Buffer.data(); - if (replSource.path) - source->path = utf8Buffer.data(); - if (replSource.query) - source->query = utf8Buffer.data(); - if (replSource.ref) - source->ref = utf8Buffer.data(); - - return success; -} - -#if !OS(WINDOWS) -int _itoa_s(int value, char* buffer, size_t sizeInChars, int radix) -{ - int written; - if (radix == 10) - written = snprintf(buffer, sizeInChars, "%d", value); - else if (radix == 16) - written = snprintf(buffer, sizeInChars, "%x", value); - else - return EINVAL; - - if (static_cast<size_t>(written) >= sizeInChars) { - // Output was truncated, or written was negative. - return EINVAL; - } - return 0; -} - -int _itow_s(int value, UChar* buffer, size_t sizeInChars, int radix) -{ - if (radix != 10) - return EINVAL; - - // No more than 12 characters will be required for a 32-bit integer. - // Add an extra byte for the terminating null. - char temp[13]; - int written = snprintf(temp, sizeof(temp), "%d", value); - if (static_cast<size_t>(written) >= sizeInChars) { - // Output was truncated, or written was negative. - return EINVAL; - } - - for (int i = 0; i < written; ++i) - buffer[i] = static_cast<UChar>(temp[i]); - buffer[written] = '\0'; - return 0; -} - -#endif // !OS(WINDOWS) - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonInternal.h b/Source/WTF/wtf/url/src/URLCanonInternal.h deleted file mode 100644 index 9b2970632..000000000 --- a/Source/WTF/wtf/url/src/URLCanonInternal.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2011 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// This file is intended to be included in another C++ file where the character -// types are defined. This allows us to write mostly generic code, but not have -// templace bloat because everything is inlined when anybody calls any of our -// functions. - -#ifndef URLCanonInternal_h -#define URLCanonInternal_h - -#include "URLCanon.h" -#include "URLCharacterTypes.h" -#include <stdlib.h> -#include <wtf/HexNumber.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -// Appends the given string to the output, escaping characters that do not -// match the given |type| in SharedCharTypes. -void appendStringOfType(const char* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output); -void appendStringOfType(const UChar* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output); - -// This lookup table allows fast conversion between ASCII hex letters and their -// corresponding numerical value. The 8-bit range is divided up into 8 -// regions of 0x20 characters each. Each of the three character types (numbers, -// uppercase, lowercase) falls into different regions of this range. The table -// contains the amount to subtract from characters in that range to get at -// the corresponding numerical value. -// -// See HexDigitToValue for the lookup. -extern const char kCharToHexLookup[8]; - -// Assumes the input is a valid hex digit! Call isHexChar before using this. -inline unsigned char hexCharToValue(unsigned char character) -{ - return character - kCharToHexLookup[character / 0x20]; -} - -// Indicates if the given character is a dot or dot equivalent, returning the -// number of characters taken by it. This will be one for a literal dot, 3 for -// an escaped dot. If the character is not a dot, this will return 0. -template<typename CharacterType> -inline int isDot(const CharacterType* spec, int offset, int end) -{ - if (spec[offset] == '.') - return 1; - - if (spec[offset] == '%' && offset + 3 <= end && spec[offset + 1] == '2' && (spec[offset + 2] == 'e' || spec[offset + 2] == 'E')) { - // Found "%2e" - return 3; - } - return 0; -} - -// Returns the canonicalized version of the input character according to scheme -// rules. This is implemented alongside the scheme canonicalizer, and is -// required for relative URL resolving to test for scheme equality. -// -// Returns 0 if the input character is not a valid scheme character. -char canonicalSchemeChar(UChar); - -// Write a single character, escaped, to the output. This always escapes: it -// does no checking that thee character requires escaping. -// Escaping makes sense only 8 bit chars, so code works in all cases of -// input parameters (8/16bit). -template<typename InChar, typename OutChar> -inline void appendURLEscapedCharacter(InChar character, URLBuffer<OutChar>& buffer) -{ - buffer.append('%'); - buffer.append(WTF::Internal::upperHexDigits[character >> 4]); - buffer.append(WTF::Internal::upperHexDigits[character & 0xf]); -} - -// The character we'll substitute for undecodable or invalid characters. -extern const UChar kUnicodeReplacementCharacter; - -// UTF-8 functions ------------------------------------------------------------ - -// Reads one character in UTF-8 starting at |*begin| in |str| and places -// the decoded value into |*codePoint|. If the character is valid, we will -// return true. If invalid, we'll return false and put the -// kUnicodeReplacementCharacter into |*codePoint|. -// -// |*begin| will be updated to point to the last character consumed so it -// can be incremented in a loop and will be ready for the next character. -// (for a single-byte ASCII character, it will not be changed). -// -// Implementation is in URLCanonicalizer_icu.cc. -bool readUTFChar(const char* str, int* begin, int length, unsigned* codePointOut); - -// Generic To-UTF-8 converter. This will call the given append method for each -// character that should be appended, with the given output method. Wrappers -// are provided below for escaped and non-escaped versions of this. -// -// The charactervalue must have already been checked that it's a valid Unicode -// character. -template<class Output, void appendFunction(unsigned char, Output&)> -inline void doAppendUTF8(unsigned charactervalue, Output& output) -{ - if (charactervalue <= 0x7f) { - appendFunction(static_cast<unsigned char>(charactervalue), output); - } else if (charactervalue <= 0x7ff) { - // 110xxxxx 10xxxxxx - appendFunction(static_cast<unsigned char>(0xC0 | (charactervalue >> 6)), output); - appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); - } else if (charactervalue <= 0xffff) { - // 1110xxxx 10xxxxxx 10xxxxxx - appendFunction(static_cast<unsigned char>(0xe0 | (charactervalue >> 12)), output); - appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 6) & 0x3f)), output); - appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); - } else if (charactervalue <= 0x10FFFF) { // Max unicode code point. - // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - appendFunction(static_cast<unsigned char>(0xf0 | (charactervalue >> 18)), output); - appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 12) & 0x3f)), output); - appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 6) & 0x3f)), output); - appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); - } else { - // Invalid UTF-8 character (>20 bits). - ASSERT_NOT_REACHED(); - } -} - -// Helper used by AppendUTF8Value below. We use an unsigned parameter so there -// are no funny sign problems with the input, but then have to convert it to -// a regular char for appending. -inline void AppendCharToOutput(unsigned char character, URLBuffer<char>& output) -{ - output.append(static_cast<char>(character)); -} - -// Writes the given character to the output as UTF-8. This does NO checking -// of the validity of the unicode characters; the caller should ensure that -// the value it is appending is valid to append. -inline void AppendUTF8Value(unsigned charactervalue, URLBuffer<char>& output) -{ - doAppendUTF8<URLBuffer<char>, AppendCharToOutput>(charactervalue, output); -} - -// Writes the given character to the output as UTF-8, escaping ALL -// characters (even when they are ASCII). This does NO checking of the -// validity of the unicode characters; the caller should ensure that the value -// it is appending is valid to append. -inline void AppendUTF8EscapedValue(unsigned charactervalue, URLBuffer<char>& output) -{ - doAppendUTF8<URLBuffer<char>, appendURLEscapedCharacter>(charactervalue, output); -} - -// UTF-16 functions ----------------------------------------------------------- - -// Reads one character in UTF-16 starting at |*begin| in |str| and places -// the decoded value into |*codePoint|. If the character is valid, we will -// return true. If invalid, we'll return false and put the -// kUnicodeReplacementCharacter into |*codePoint|. -// -// |*begin| will be updated to point to the last character consumed so it -// can be incremented in a loop and will be ready for the next character. -// (for a single-16-bit-word character, it will not be changed). -// -// Implementation is in URLCanonicalizer_icu.cc. -bool readUTFChar(const UChar* str, int* begin, int length, unsigned* codePoint); - -// Equivalent to U16_APPEND_UNSAFE in ICU but uses our output method. -inline void AppendUTF16Value(unsigned codePoint, URLBuffer<UChar>& output) -{ - if (codePoint > 0xffff) { - output.append(static_cast<UChar>((codePoint >> 10) + 0xd7c0)); - output.append(static_cast<UChar>((codePoint & 0x3ff) | 0xdc00)); - } else - output.append(static_cast<UChar>(codePoint)); -} - -// Escaping functions --------------------------------------------------------- - -// Writes the given character to the output as UTF-8, escaped. Call this -// function only when the input is wide. Returns true on success. Failure -// means there was some problem with the encoding, we'll still try to -// update the |*begin| pointer and add a placeholder character to the -// output so processing can continue. -// -// We will append the character starting at ch[begin] with the buffer ch -// being |length|. |*begin| will be updated to point to the last character -// consumed (we may consume more than one for UTF-16) so that if called in -// a loop, incrementing the pointer will move to the next character. -// -// Every single output character will be escaped. This means that if you -// give it an ASCII character as input, it will be escaped. Some code uses -// this when it knows that a character is invalid according to its rules -// for validity. If you don't want escaping for ASCII characters, you will -// have to filter them out prior to calling this function. -// -// Assumes that ch[begin] is within range in the array, but does not assume -// that any following characters are. -inline bool AppendUTF8EscapedChar(const UChar* str, int* begin, int length, URLBuffer<char>& output) -{ - // UTF-16 input. ReadUChar will handle invalid characters for us and give - // us the kUnicodeReplacementCharacter, so we don't have to do special - // checking after failure, just pass through the failure to the caller. - unsigned charactervalue; - bool success = readUTFChar(str, begin, length, &charactervalue); - AppendUTF8EscapedValue(charactervalue, output); - return success; -} - -// Handles UTF-8 input. See the wide version above for usage. -inline bool AppendUTF8EscapedChar(const char* str, int* begin, int length, URLBuffer<char>& output) -{ - // ReadUTF8Char will handle invalid characters for us and give us the - // kUnicodeReplacementCharacter, so we don't have to do special checking - // after failure, just pass through the failure to the caller. - unsigned ch; - bool success = readUTFChar(str, begin, length, &ch); - AppendUTF8EscapedValue(ch, output); - return success; -} - -// Given a '%' character at |*begin| in the string |spec|, this will decode -// the escaped value and put it into |*unescapedValue| on success (returns -// true). On failure, this will return false, and will not write into -// |*unescapedValue|. -// -// |*begin| will be updated to point to the last character of the escape -// sequence so that when called with the index of a for loop, the next time -// through it will point to the next character to be considered. On failure, -// |*begin| will be unchanged. -inline bool Is8BitChar(char) -{ - return true; // this case is specialized to avoid a warning -} -inline bool Is8BitChar(UChar c) -{ - return c <= 255; -} - -template<typename CHAR> -inline bool DecodeEscaped(const CHAR* spec, int* begin, int end, unsigned char* unescapedValue) -{ - if (*begin + 3 > end || !Is8BitChar(spec[*begin + 1]) || !Is8BitChar(spec[*begin + 2])) { - // Invalid escape sequence because there's not enough room, or the - // digits are not ASCII. - return false; - } - - unsigned char first = static_cast<unsigned char>(spec[*begin + 1]); - unsigned char second = static_cast<unsigned char>(spec[*begin + 2]); - if (!URLCharacterTypes::isHexChar(first) || !URLCharacterTypes::isHexChar(second)) { - // Invalid hex digits, fail. - return false; - } - - // Valid escape sequence. - *unescapedValue = (hexCharToValue(first) << 4) + hexCharToValue(second); - *begin += 2; - return true; -} - -// Appends the given substring to the output, escaping "some" characters that -// it feels may not be safe. It assumes the input values are all contained in -// 8-bit although it allows any type. -// -// This is used in error cases to append invalid output so that it looks -// approximately correct. Non-error cases should not call this function since -// the escaping rules are not guaranteed! -void AppendInvalidNarrowString(const char* spec, int begin, int end, URLBuffer<char>& output); -void AppendInvalidNarrowString(const UChar* spec, int begin, int end, URLBuffer<char>& output); - -// Misc canonicalization helpers ---------------------------------------------- - -// Converts between UTF-8 and UTF-16, returning true on successful conversion. -// The output will be appended to the given canonicalizer output (so make sure -// it's empty if you want to replace). -// -// On invalid input, this will still write as much output as possible, -// replacing the invalid characters with the "invalid character". It will -// return false in the failure case, and the caller should not continue as -// normal. -bool ConvertUTF16ToUTF8(const UChar* input, int inputLength, URLBuffer<char>& output); -bool ConvertUTF8ToUTF16(const char* input, int inputLength, URLBuffer<UChar>& output); - -// Converts from UTF-16 to 8-bit using the character set converter. If the -// converter is null, this will use UTF-8. -void ConvertUTF16ToQueryEncoding(const UChar* input, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>& output); - -// Applies the replacements to the given component source. The component source -// should be pre-initialized to the "old" base. That is, all pointers will -// point to the spec of the old URL, and all of the Parsed components will -// be indices into that string. -// -// The pointers and components in the |source| for all non-null strings in the -// |repl| (replacements) will be updated to reference those strings. -// Canonicalizing with the new |source| and |parsed| can then combine URL -// components from many different strings. -void SetupOverrideComponents(const char* base, - const Replacements<char>&, - URLComponentSource<char>*, - URLSegments* parsed); - -// Like the above 8-bit version, except that it additionally converts the -// UTF-16 input to UTF-8 before doing the overrides. -// -// The given utf8Buffer is used to store the converted components. They will -// be appended one after another, with the parsed structure identifying the -// appropriate substrings. This buffer is a parameter because the source has -// no storage, so the buffer must have the same lifetime as the source -// parameter owned by the caller. -// -// THE CALLER MUST NOT ADD TO THE |utf8Buffer| AFTER THIS CALL. Members of -// |source| will point into this buffer, which could be invalidated if -// additional data is added and the CanonOutput resizes its buffer. -// -// Returns true on success. Fales means that the input was not valid UTF-16, -// although we will have still done the override with "invalid characters" in -// place of errors. -bool SetupUTF16OverrideComponents(const char* base, - const Replacements<UChar>&, - URLBuffer<char>& utf8Buffer, - URLComponentSource<char>*, - URLSegments* parsed); - -// Implemented in URLCanonicalizer_path.cc, these are required by the relative URL -// resolver as well, so we declare them here. -bool CanonicalizePartialPath(const char* spec, - const URLComponent& path, - int pathBeginInOutput, - URLBuffer<char>& output); -bool CanonicalizePartialPath(const UChar* spec, - const URLComponent& path, - int pathBeginInOutput, - URLBuffer<char>& output); - -#if !OS(WINDOWS) -// Implementations of Windows' int-to-string conversions -int _itoa_s(int value, char* buffer, size_t sizeInChars, int radix); -int _itow_s(int value, UChar* buffer, size_t sizeInChars, int radix); - -// Secure template overloads for these functions -template<size_t N> -inline int _itoa_s(int value, char (&buffer)[N], int radix) -{ - return _itoa_s(value, buffer, N, radix); -} - -template<size_t N> -inline int _itow_s(int value, UChar (&buffer)[N], int radix) -{ - return _itow_s(value, buffer, N, radix); -} - -// _strtoui64 and strtoull behave the same -inline unsigned long long _strtoui64(const char* nptr, char** endptr, int base) -{ - return strtoull(nptr, endptr, base); -} -#endif // OS(WINDOWS) - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLCanonInternal_h diff --git a/Source/WTF/wtf/url/src/URLCanonMailto.cpp b/Source/WTF/wtf/url/src/URLCanonMailto.cpp deleted file mode 100644 index bdb353845..000000000 --- a/Source/WTF/wtf/url/src/URLCanonMailto.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2008 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Functions for canonicalizing "mailto:" URLs. - -#include "config.h" -#include "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" -#include "URLFile.h" -#include "URLParseInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - - -template<typename CharacterType, typename UCHAR> -bool doCanonicalizeMailtoURL(const URLComponentSource<CharacterType>& source, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) -{ - // mailto: only uses {scheme, path, query} -- clear the rest. - outputParsed.username = URLComponent(); - outputParsed.password = URLComponent(); - outputParsed.host = URLComponent(); - outputParsed.port = URLComponent(); - outputParsed.fragment = URLComponent(); - - // Scheme (known, so we don't bother running it through the more - // complicated scheme canonicalizer). - outputParsed.scheme.setBegin(output.length()); - output.append("mailto:", 7); - outputParsed.scheme.setLength(6); - - bool success = true; - - // Path - if (parsed.path.isValid()) { - outputParsed.path.setBegin(output.length()); - - // Copy the path using path URL's more lax escaping rules. - // We convert to UTF-8 and escape non-ASCII, but leave all - // ASCII characters alone. - int end = parsed.path.end(); - for (int i = parsed.path.begin(); i < end; ++i) { - UCHAR uch = static_cast<UCHAR>(source.path[i]); - if (uch < 0x20 || uch >= 0x80) - success &= AppendUTF8EscapedChar(source.path, &i, end, output); - else - output.append(static_cast<char>(uch)); - } - - outputParsed.path.setLength(output.length() - outputParsed.path.begin()); - } else { - // No path at all - outputParsed.path.reset(); - } - - // Query -- always use the default utf8 charset converter. - CanonicalizeQuery(source.query, parsed.query, 0, output, &outputParsed.query); - - return success; -} - -} // namespace - -bool canonicalizeMailtoURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) -{ - return doCanonicalizeMailtoURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, output, outputParsed); -} - -bool canonicalizeMailtoURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) -{ - return doCanonicalizeMailtoURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, output, outputParsed); -} - -bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, - const Replacements<char>& replacements, - URLBuffer<char>& output, URLSegments& outputParsed) -{ - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupOverrideComponents(base, replacements, &source, &parsed); - return doCanonicalizeMailtoURL<char, unsigned char>(source, parsed, output, outputParsed); -} - -bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, - const Replacements<UChar>& replacements, - URLBuffer<char>& output, URLSegments& outputParsed) -{ - RawURLBuffer<char> utf8; - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); - return doCanonicalizeMailtoURL<char, unsigned char>(source, parsed, output, outputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonPath.cpp b/Source/WTF/wtf/url/src/URLCanonPath.cpp deleted file mode 100644 index 9bc443fd7..000000000 --- a/Source/WTF/wtf/url/src/URLCanonPath.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Canonicalization functions for the paths of URLs. - -#include "config.h" -#include "URLCanon.h" - -#include "URLCanonInternal.h" -#include "URLParseInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -enum CharacterFlags { - // Pass through unchanged, whether escaped or unescaped. This doesn't - // actually set anything so you can't OR it to check, it's just to make the - // table below more clear when neither ESCAPE or UNESCAPE is set. - PASS = 0, - - // This character requires special handling in doPartialPath. Doing this test - // first allows us to filter out the common cases of regular characters that - // can be directly copied. - SPECIAL = 1, - - // This character must be escaped in the canonical output. Note that all - // escaped chars also have the "special" bit set so that the code that looks - // for this is triggered. Not valid with PASS or ESCAPE - ESCAPE_BIT = 2, - ESCAPE = ESCAPE_BIT | SPECIAL, - - // This character must be unescaped in canonical output. Not valid with - // ESCAPE or PASS. We DON'T set the SPECIAL flag since if we encounter these - // characters unescaped, they should just be copied. - UNESCAPE = 4, - - // This character is disallowed in URLs. Note that the "special" bit is also - // set to trigger handling. - INVALID_BIT = 8, - INVALID = INVALID_BIT | SPECIAL, -}; - -// This table contains one of the above flag values. Note some flags are more -// than one bits because they also turn on the "special" flag. Special is the -// only flag that may be combined with others. -// -// This table is designed to match exactly what IE does with the characters. -// -// Dot is even more special, and the escaped version is handled specially by -// isDot. Therefore, we don't need the "escape" flag, and even the "unescape" -// bit is never handled (we just need the "special") bit. -const unsigned char kPathCharLookup[0x100] = { -// null control chars... - INVALID, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, -// control chars... - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, -// ' ' ! " # $ % & ' ( ) * + , - . / - ESCAPE, PASS, ESCAPE, ESCAPE, PASS, ESCAPE, PASS, PASS, PASS, PASS, PASS, PASS, PASS, UNESCAPE, SPECIAL, PASS, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, PASS, PASS, ESCAPE, PASS, ESCAPE, ESCAPE, -// @ A B C D E F G H I J K L M N O - PASS, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, -// P Q R S T U V W X Y Z [ \ ] ^ _ - UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, PASS, ESCAPE, PASS, ESCAPE, UNESCAPE, -// ` a b c d e f g h i j k l m n o - ESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, -// p q r s t u v w x y z { | } ~ <NBSP> - UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, ESCAPE, ESCAPE, ESCAPE, UNESCAPE, ESCAPE, -// ...all the high-bit characters are escaped - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, - ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE}; - -enum DotDisposition { - // The given dot is just part of a filename and is not special. - NOT_A_DIRECTORY, - - // The given dot is the current directory. - DIRECTORY_CUR, - - // The given dot is the first of a double dot that should take us up one. - DIRECTORY_UP -}; - -// When the path resolver finds a dot, this function is called with the -// character following that dot to see what it is. The return value -// indicates what type this dot is (see above). This code handles the case -// where the dot is at the end of the input. -// -// |*consumedLength| will contain the number of characters in the input that -// express what we found. -// -// If the input is "../foo", |afterDot| = 1, |end| = 6, and -// at the end, |*consumedLength| = 2 for the "./" this function consumed. The -// original dot length should be handled by the caller. -template<typename CHAR> -DotDisposition ClassifyAfterDot(const CHAR* spec, int afterDot, int end, int* consumedLength) -{ - if (afterDot == end) { - // Single dot at the end. - *consumedLength = 0; - return DIRECTORY_CUR; - } - if (URLParser::isURLSlash(spec[afterDot])) { - // Single dot followed by a slash. - *consumedLength = 1; // Consume the slash - return DIRECTORY_CUR; - } - - int secondDotLength = isDot(spec, afterDot, end); - if (secondDotLength) { - int afterSecondDot = afterDot + secondDotLength; - if (afterSecondDot == end) { - // Double dot at the end. - *consumedLength = secondDotLength; - return DIRECTORY_UP; - } - if (URLParser::isURLSlash(spec[afterSecondDot])) { - // Double dot followed by a slash. - *consumedLength = secondDotLength + 1; - return DIRECTORY_UP; - } - } - - // The dots are followed by something else, not a directory. - *consumedLength = 0; - return NOT_A_DIRECTORY; -} - -// Rewinds the output to the previous slash. It is assumed that the output -// ends with a slash and this doesn't count (we call this when we are -// appending directory paths, so the previous path component has and ending -// slash). -// -// This will stop at the first slash (assumed to be at position -// |pathBeginInOutput| and not go any higher than that. Some web pages -// do ".." too many times, so we need to handle that brokenness. -// -// It searches for a literal slash rather than including a backslash as well -// because it is run only on the canonical output. -// -// The output is guaranteed to end in a slash when this function completes. -void BackUpToPreviousSlash(int pathBeginInOutput, URLBuffer<char>& output) -{ - ASSERT(output.length() > 0); - - int i = output.length() - 1; - ASSERT(output.at(i) == '/'); - if (i == pathBeginInOutput) - return; // We're at the first slash, nothing to do. - - // Now back up (skipping the trailing slash) until we find another slash. - i--; - while (output.at(i) != '/' && i > pathBeginInOutput) - i--; - - // Now shrink the output to just include that last slash we found. - output.setLength(i + 1); -} - -// Appends the given path to the output. It assumes that if the input path -// starts with a slash, it should be copied to the output. If no path has -// already been appended to the output (the case when not resolving -// relative URLs), the path should begin with a slash. -// -// If there are already path components (this mode is used when appending -// relative paths for resolving), it assumes that the output already has -// a trailing slash and that if the input begins with a slash, it should be -// copied to the output. -// -// We do not collapse multiple slashes in a row to a single slash. It seems -// no web browsers do this, and we don't want incompababilities, even though -// it would be correct for most systems. -template<typename CharacterType, typename UCHAR> -bool doPartialPath(const CharacterType* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) -{ - int end = path.end(); - - bool success = true; - for (int i = path.begin(); i < end; ++i) { - UCHAR uch = static_cast<UCHAR>(spec[i]); - if (sizeof(CharacterType) > sizeof(char) && uch >= 0x80) { - // We only need to test wide input for having non-ASCII characters. For - // narrow input, we'll always just use the lookup table. We don't try to - // do anything tricky with decoding/validating UTF-8. This function will - // read one or two UTF-16 characters and append the output as UTF-8. This - // call will be removed in 8-bit mode. - success &= AppendUTF8EscapedChar(spec, &i, end, output); - } else { - // Normal ASCII character or 8-bit input, use the lookup table. - unsigned char outCh = static_cast<unsigned char>(uch); - unsigned char flags = kPathCharLookup[outCh]; - if (flags & SPECIAL) { - // Needs special handling of some sort. - int dotlen; - if ((dotlen = isDot(spec, i, end)) > 0) { - // See if this dot was preceeded by a slash in the output. We - // assume that when canonicalizing paths, they will always - // start with a slash and not a dot, so we don't have to - // bounds check the output. - // - // Note that we check this in the case of dots so we don't have to - // special case slashes. Since slashes are much more common than - // dots, this actually increases performance measurably (though - // slightly). - ASSERT(output.length() > pathBeginInOutput); - if (output.length() > pathBeginInOutput && output.at(output.length() - 1) == '/') { - // Slash followed by a dot, check to see if this is means relative - int consumedLength; - switch (ClassifyAfterDot<CharacterType>(spec, i + dotlen, end, &consumedLength)) { - case NOT_A_DIRECTORY: - // Copy the dot to the output, it means nothing special. - output.append('.'); - i += dotlen - 1; - break; - case DIRECTORY_CUR: // Current directory, just skip the input. - i += dotlen + consumedLength - 1; - break; - case DIRECTORY_UP: - BackUpToPreviousSlash(pathBeginInOutput, output); - i += dotlen + consumedLength - 1; - break; - } - } else { - // This dot is not preceeded by a slash, it is just part of some - // file name. - output.append('.'); - i += dotlen - 1; - } - } else if (outCh == '\\') { - // Convert backslashes to forward slashes - output.append('/'); - } else if (outCh == '%') { - // Handle escape sequences. - unsigned char unescapedValue; - if (DecodeEscaped(spec, &i, end, &unescapedValue)) { - // Valid escape sequence, see if we keep, reject, or unescape it. - char unescapedFlags = kPathCharLookup[unescapedValue]; - - if (unescapedFlags & UNESCAPE) { - // This escaped value shouldn't be escaped, copy it. - output.append(unescapedValue); - } else if (unescapedFlags & INVALID_BIT) { - // Invalid escaped character, copy it and remember the error. - output.append('%'); - output.append(static_cast<char>(spec[i - 1])); - output.append(static_cast<char>(spec[i])); - success = false; - } else { - // Valid escaped character but we should keep it escaped. We - // don't want to change the case of any hex letters in case - // the server is sensitive to that, so we just copy the two - // characters without checking (DecodeEscape will have advanced - // to the last character of the pair). - output.append('%'); - output.append(static_cast<char>(spec[i - 1])); - output.append(static_cast<char>(spec[i])); - } - } else { - // Invalid escape sequence. IE7 rejects any URLs with such - // sequences, while Firefox, IE6, and Safari all pass it through - // unchanged. We are more permissive unlike IE7. I don't think this - // can cause significant problems, if it does, we should change - // to be more like IE7. - output.append('%'); - } - - } else if (flags & INVALID_BIT) { - // For NULLs, etc. fail. - appendURLEscapedCharacter(outCh, output); - success = false; - - } else if (flags & ESCAPE_BIT) { - // This character should be escaped. - appendURLEscapedCharacter(outCh, output); - } - } else { - // Nothing special about this character, just append it. - output.append(outCh); - } - } - } - return success; -} - -template<typename CharacterType, typename UCHAR> -bool doPath(const CharacterType* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent& outputPath) -{ - bool success = true; - outputPath.setBegin(output.length()); - if (path.length() > 0) { - // Write out an initial slash if the input has none. If we just parse a URL - // and then canonicalize it, it will of course have a slash already. This - // check is for the replacement and relative URL resolving cases of file - // URLs. - if (!URLParser::isURLSlash(spec[path.begin()])) - output.append('/'); - - success = doPartialPath<CharacterType, UCHAR>(spec, path, outputPath.begin(), output); - } else { - // No input, canonical path is a slash. - output.append('/'); - } - outputPath.setLength(output.length() - outputPath.begin()); - return success; -} - -} // namespace - -bool CanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent* outputPath) -{ - return doPath<char, unsigned char>(spec, path, output, *outputPath); -} - -bool CanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent* outputPath) -{ - return doPath<UChar, UChar>(spec, path, output, *outputPath); -} - -bool CanonicalizePartialPath(const char* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) -{ - return doPartialPath<char, unsigned char>(spec, path, pathBeginInOutput, output); -} - -bool CanonicalizePartialPath(const UChar* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) -{ - return doPartialPath<UChar, UChar>(spec, path, pathBeginInOutput, output); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonPathurl.cpp b/Source/WTF/wtf/url/src/URLCanonPathurl.cpp deleted file mode 100644 index cea037c21..000000000 --- a/Source/WTF/wtf/url/src/URLCanonPathurl.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Functions for canonicalizing "path" URLs. Not to be confused with the path -// of a URL, these are URLs that have no authority section, only a path. For -// example, "javascript:" and "data:". - -#include "config.h" -#include "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -template<typename CharacterType, typename UCHAR> -bool doCanonicalizePathURL(const URLComponentSource<CharacterType>& source, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) -{ - // Scheme: this will append the colon. - bool success = canonicalizeScheme(source.scheme, parsed.scheme, output, ouputParsed.scheme); - - // We assume there's no authority for path URLs. Note that hosts should never - // have -1 length. - ouputParsed.username.reset(); - ouputParsed.password.reset(); - ouputParsed.host.reset(); - ouputParsed.port.reset(); - - if (parsed.path.isValid()) { - // Copy the path using path URL's more lax escaping rules (think for - // javascript:). We convert to UTF-8 and escape non-ASCII, but leave all - // ASCII characters alone. This helps readability of JavaStript. - ouputParsed.path.setBegin(output.length()); - int end = parsed.path.end(); - for (int i = parsed.path.begin(); i < end; ++i) { - UCHAR uch = static_cast<UCHAR>(source.path[i]); - if (uch < 0x20 || uch >= 0x80) - success &= AppendUTF8EscapedChar(source.path, &i, end, output); - else - output.append(static_cast<char>(uch)); - } - ouputParsed.path.setLength(output.length() - ouputParsed.path.begin()); - } else { - // Empty path. - ouputParsed.path.reset(); - } - - // Assume there's no query or ref. - ouputParsed.query.reset(); - ouputParsed.fragment.reset(); - - return success; -} - -} // namespace - -bool canonicalizePathURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) -{ - return doCanonicalizePathURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, output, ouputParsed); -} - -bool canonicalizePathURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) -{ - return doCanonicalizePathURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, output, ouputParsed); -} - -bool ReplacePathURL(const char* base, const URLSegments& baseParsed, const Replacements<char>& replacements, URLBuffer<char>& output, URLSegments* ouputParsed) -{ - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupOverrideComponents(base, replacements, &source, &parsed); - return doCanonicalizePathURL<char, unsigned char>(source, parsed, output, *ouputParsed); -} - -bool ReplacePathURL(const char* base, const URLSegments& baseParsed, const Replacements<UChar>& replacements, URLBuffer<char>& output, URLSegments* ouputParsed) -{ - RawURLBuffer<char> utf8; - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); - return doCanonicalizePathURL<char, unsigned char>(source, parsed, output, *ouputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonQuery.cpp b/Source/WTF/wtf/url/src/URLCanonQuery.cpp deleted file mode 100644 index 0b829ba5b..000000000 --- a/Source/WTF/wtf/url/src/URLCanonQuery.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" -#include "URLCharacterTypes.h" -#include "URLQueryCharsetConverter.h" -#include <wtf/text/ASCIIFastPath.h> - -// Query canonicalization in IE -// ---------------------------- -// IE is very permissive for query parameters specified in links on the page -// (in contrast to links that it constructs itself based on form data). It does -// not unescape any character. It does not reject any escape sequence (be they -// invalid like "%2y" or freaky like %00). -// -// IE only escapes spaces and nothing else. Embedded NULLs, tabs (0x09), -// LF (0x0a), and CR (0x0d) are removed (this probably happens at an earlier -// layer since they are removed from all portions of the URL). All other -// characters are passed unmodified. Invalid UTF-16 sequences are preserved as -// well, with each character in the input being converted to UTF-8. It is the -// server's job to make sense of this invalid query. -// -// Invalid multibyte sequences (for example, invalid UTF-8 on a UTF-8 page) -// are converted to the invalid character and sent as unescaped UTF-8 (0xef, -// 0xbf, 0xbd). This may not be canonicalization, the parser may generate these -// strings before the URL handler ever sees them. -// -// Our query canonicalization -// -------------------------- -// We escape all non-ASCII characters and control characters, like Firefox. -// This is more conformant to the URL spec, and there do not seem to be many -// problems relating to Firefox's behavior. -// -// Like IE, we will never unescape (although the application may want to try -// unescaping to present the user with a more understandable URL). We will -// replace all invalid sequences (including invalid UTF-16 sequences, which IE -// doesn't) with the "invalid character," and we will escape it. - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// Returns true if the characters starting at |begin| and going until |end| -// (non-inclusive) are all representable in 7-bits. -template<typename CharacterType> -bool isAllASCII(const CharacterType* spec, const URLComponent& query) -{ - return charactersAreAllASCII(spec + query.begin(), query.length()); -} - -// FIXME: Benjamin: get rid of this when everything is based on LChar. -template<> -bool isAllASCII<char>(const char* spec, const URLComponent& query) -{ - return charactersAreAllASCII(reinterpret_cast<const LChar*>(spec + query.begin()), query.length()); -} - -// Appends the given string to the output, escaping characters that do not -// match the given |type| in SharedCharTypes. This version will accept 8 or 16 -// bit characters, but assumes that they have only 7-bit values. It also assumes -// that all UTF-8 values are correct, so doesn't bother checking -template<typename CharacterType> -void appendRaw8BitQueryString(const CharacterType* source, int length, URLBuffer<char>& output) -{ - for (int i = 0; i < length; ++i) { - if (!URLCharacterTypes::isQueryChar(static_cast<unsigned char>(source[i]))) - appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), output); - else // Doesn't need escaping. - output.append(static_cast<char>(source[i])); - } -} - -// Runs the converter on the given UTF-8 input. Since the converter expects -// UTF-16, we have to convert first. The converter must be non-null. -void runConverter(const char* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) -{ - // This function will replace any misencoded values with the invalid - // character. This is what we want so we don't have to check for error. - RawURLBuffer<UChar> utf16; - ConvertUTF8ToUTF16(&spec[query.begin()], query.length(), utf16); - converter->convertFromUTF16(utf16.data(), utf16.length(), output); -} - -// Runs the converter with the given UTF-16 input. We don't have to do -// anything, but this overriddden function allows us to use the same code -// for both UTF-8 and UTF-16 input. -void runConverter(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) -{ - converter->convertFromUTF16(&spec[query.begin()], query.length(), output); -} - -template<typename CharacterType> -void doConvertToQueryEncoding(const CharacterType* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) -{ - if (isAllASCII(spec, query)) { - // Easy: the input can just appended with no character set conversions. - appendRaw8BitQueryString(&spec[query.begin()], query.length(), output); - } else { - // Harder: convert to the proper encoding first. - if (converter) { - // Run the converter to get an 8-bit string, then append it, escaping - // necessary values. - RawURLBuffer<char> eightBitQueryString; - runConverter(spec, query, converter, eightBitQueryString); - appendRaw8BitQueryString(eightBitQueryString.data(), eightBitQueryString.length(), output); - } else { - // No converter, do our own UTF-8 conversion. - appendStringOfType(&spec[query.begin()], query.length(), URLCharacterTypes::QueryCharacter, output); - } - } -} - -template<typename CharacterType> -void doCanonicalizeQuery(const CharacterType* spec, const URLComponent& query, URLQueryCharsetConverter* converter, - URLBuffer<char>& output, URLComponent& outputQueryComponent) -{ - if (query.length() < 0) { - outputQueryComponent = URLComponent(); - return; - } - - output.append('?'); - outputQueryComponent.setBegin(output.length()); - - doConvertToQueryEncoding<CharacterType>(spec, query, converter, output); - - outputQueryComponent.setLength(output.length() - outputQueryComponent.begin()); -} - -} // namespace - -void CanonicalizeQuery(const char* spec, const URLComponent& query, URLQueryCharsetConverter* converter, - URLBuffer<char>& output, URLComponent* outputQueryComponent) -{ - doCanonicalizeQuery(spec, query, converter, output, *outputQueryComponent); -} - -void CanonicalizeQuery(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter* converter, - URLBuffer<char>& output, URLComponent* outputQueryComponent) -{ - doCanonicalizeQuery(spec, query, converter, output, *outputQueryComponent); -} - -void ConvertUTF16ToQueryEncoding(const UChar* input, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) -{ - doConvertToQueryEncoding<UChar>(input, query, converter, output); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonRelative.cpp b/Source/WTF/wtf/url/src/URLCanonRelative.cpp deleted file mode 100644 index 7ef050064..000000000 --- a/Source/WTF/wtf/url/src/URLCanonRelative.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Canonicalizer functions for working with and resolving relative URLs. - -#include "config.h" -#include "URLCanon.h" - -#include "URLCanonInternal.h" -#include "URLFile.h" -#include "URLParseInternal.h" -#include "URLUtilInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -// Firefox does a case-sensitive compare (which is probably wrong--Mozilla bug -// 379034), whereas IE is case-insensetive. -// -// We choose to be more permissive like IE. We don't need to worry about -// unescaping or anything here: neither IE or Firefox allow this. We also -// don't have to worry about invalid scheme characters since we are comparing -// against the canonical scheme of the base. -// -// The base URL should always be canonical, therefore is ASCII. -template<typename CHAR> -bool AreSchemesEqual(const char* base, - const URLComponent& baseScheme, - const CHAR* cmp, - const URLComponent& cmpScheme) -{ - if (baseScheme.length() != cmpScheme.length()) - return false; - for (int i = 0; i < baseScheme.length(); i++) { - // We assume the base is already canonical, so we don't have to - // canonicalize it. - if (canonicalSchemeChar(cmp[cmpScheme.begin() + i]) != - base[baseScheme.begin() + i]) - return false; - } - return true; -} - -#if OS(WINDOWS) -// Here, we also allow Windows paths to be represented as "/C:/" so we can be -// consistent about URL paths beginning with slashes. This function is like -// DoesBeginWindowsDrivePath except that it also requires a slash at the -// beginning. -template<typename CHAR> -bool doesBeginSlashWindowsDriveSpec(const CHAR* spec, int startOffset, int specLength) -{ - if (startOffset >= specLength) - return false; - return URLParser::isURLSlash(spec[startOffset]) && URLParser::doesBeginWindowsDriveSpec(spec, startOffset + 1, specLength); -} - -#endif // OS(WINDOWS) - -// See isRelativeURL in the header file for usage. -template<typename CharacterType> -bool doIsRelativeURL(const char* base, const URLSegments& baseParsed, - const CharacterType* url, int urlLength, - bool isBaseHierarchical, - bool& isRelative, URLComponent& relativeComponent) -{ - isRelative = false; // So we can default later to not relative. - - // Trim whitespace and construct a new range for the substring. - int begin = 0; - URLParser::trimURL(url, begin, urlLength); - if (begin >= urlLength) { - // Empty URLs are relative, but do nothing. - relativeComponent = URLComponent(begin, 0); - isRelative = true; - return true; - } - -#if OS(WINDOWS) - // We special case paths like "C:\foo" so they can link directly to the - // file on Windows (IE compatability). The security domain stuff should - // prevent a link like this from actually being followed if its on a - // web page. - // - // We treat "C:/foo" as an absolute URL. We can go ahead and treat "/c:/" - // as relative, as this will just replace the path when the base scheme - // is a file and the answer will still be correct. - // - // We require strict backslashes when detecting UNC since two forward - // shashes should be treated a a relative URL with a hostname. - if (URLParser::doesBeginWindowsDriveSpec(url, begin, urlLength) || URLParser::doesBeginUNCPath(url, begin, urlLength, true)) - return true; -#endif // OS(WINDOWS) - - // See if we've got a scheme, if not, we know this is a relative URL. - // BUT: Just because we have a scheme, doesn't make it absolute. - // "http:foo.html" is a relative URL with path "foo.html". If the scheme is - // empty, we treat it as relative (":foo") like IE does. - URLComponent scheme; - if (!URLParser::ExtractScheme(url, urlLength, &scheme) || !scheme.length()) { - // Don't allow relative URLs if the base scheme doesn't support it. - if (!isBaseHierarchical) - return false; - - relativeComponent = URLComponent::fromRange(begin, urlLength); - isRelative = true; - return true; - } - - // If the scheme isn't valid, then it's relative. - int schemeEnd = scheme.end(); - for (int i = scheme.begin(); i < schemeEnd; i++) { - if (!canonicalSchemeChar(url[i])) { - relativeComponent = URLComponent::fromRange(begin, urlLength); - isRelative = true; - return true; - } - } - - // If the scheme is not the same, then we can't count it as relative. - if (!AreSchemesEqual(base, baseParsed.scheme, url, scheme)) - return true; - - // When the scheme that they both share is not hierarchical, treat the - // incoming scheme as absolute (this way with the base of "data:foo", - // "data:bar" will be reported as absolute. - if (!isBaseHierarchical) - return true; - - int colonOffset = scheme.end(); - - // If it's a filesystem URL, the only valid way to make it relative is not to - // supply a scheme. There's no equivalent to e.g. http:index.html. - if (URLUtilities::CompareSchemeComponent(url, scheme, "filesystem")) - return true; - - // ExtractScheme guarantees that the colon immediately follows what it - // considers to be the scheme. countConsecutiveSlashes will handle the - // case where the begin offset is the end of the input. - int numSlashes = URLParser::countConsecutiveSlashes(url, colonOffset + 1, urlLength); - - if (!numSlashes || numSlashes == 1) { - // No slashes means it's a relative path like "http:foo.html". One slash - // is an absolute path. "http:/home/foo.html" - isRelative = true; - relativeComponent = URLComponent::fromRange(colonOffset + 1, urlLength); - return true; - } - - // Two or more slashes after the scheme we treat as absolute. - return true; -} - -// Copies all characters in the range [begin, end) of |spec| to the output, -// up until and including the last slash. There should be a slash in the -// range, if not, nothing will be copied. -// -// The input is assumed to be canonical, so we search only for exact slashes -// and not backslashes as well. We also know that it's ASCII. -void CopyToLastSlash(const char* spec, int begin, int end, URLBuffer<char>& output) -{ - // Find the last slash. - int lastSlash = -1; - for (int i = end - 1; i >= begin; --i) { - if (spec[i] == '/') { - lastSlash = i; - break; - } - } - if (lastSlash < 0) - return; // No slash. - - // Copy. - for (int i = begin; i <= lastSlash; ++i) - output.append(spec[i]); -} - -// Copies a single component from the source to the output. This is used -// when resolving relative URLs and a given component is unchanged. Since the -// source should already be canonical, we don't have to do anything special, -// and the input is ASCII. -void CopyOneComponent(const char* source, - const URLComponent& sourceComponent, - URLBuffer<char>& output, - URLComponent* outputComponent) -{ - if (sourceComponent.length() < 0) { - // This component is not present. - *outputComponent = URLComponent(); - return; - } - - outputComponent->setBegin(output.length()); - int sourceEnd = sourceComponent.end(); - for (int i = sourceComponent.begin(); i < sourceEnd; i++) - output.append(source[i]); - outputComponent->setLength(output.length() - outputComponent->begin()); -} - -#if OS(WINDOWS) - -// Called on Windows when the base URL is a file URL, this will copy the "C:" -// to the output, if there is a drive letter and if that drive letter is not -// being overridden by the relative URL. Otherwise, do nothing. -// -// It will return the index of the beginning of the next character in the -// base to be processed: if there is a "C:", the slash after it, or if -// there is no drive letter, the slash at the beginning of the path, or -// the end of the base. This can be used as the starting offset for further -// path processing. -template<typename CHAR> -int CopyBaseDriveSpecIfNecessary(const char* baseURL, - int basePathBegin, - int basePathEnd, - const CHAR* relativeURL, - int pathStart, - int relativeUrlLength, - URLBuffer<char>& output) -{ - if (basePathBegin >= basePathEnd) - return basePathBegin; // No path. - - // If the relative begins with a drive spec, don't do anything. The existing - // drive spec in the base will be replaced. - if (URLParser::doesBeginWindowsDriveSpec(relativeURL, - pathStart, relativeUrlLength)) { - return basePathBegin; // Relative URL path is "C:/foo" - } - - // The path should begin with a slash (as all canonical paths do). We check - // if it is followed by a drive letter and copy it. - if (doesBeginSlashWindowsDriveSpec(baseURL, basePathBegin, basePathEnd)) { - // Copy the two-character drive spec to the output. It will now look like - // "file:///C:" so the rest of it can be treated like a standard path. - output.append('/'); - output.append(baseURL[basePathBegin + 1]); - output.append(baseURL[basePathBegin + 2]); - return basePathBegin + 3; - } - - return basePathBegin; -} - -#endif // OS(WINDOWS) - -// A subroutine of doResolveRelativeURL, this resolves the URL knowning that -// the input is a relative path or less (qyuery or ref). -template<typename CHAR> -bool doResolveRelativePath(const char* baseURL, - const URLSegments& baseParsed, - bool /* baseIsFile */, - const CHAR* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - bool success = true; - - // We know the authority section didn't change, copy it to the output. We - // also know we have a path so can copy up to there. - URLComponent path, query, ref; - URLParser::parsePathInternal(relativeURL, - relativeComponent, - &path, - &query, - &ref); - // Canonical URLs always have a path, so we can use that offset. - output.append(baseURL, baseParsed.path.begin()); - - if (path.length() > 0) { - // The path is replaced or modified. - int truePathBegin = output.length(); - - // For file: URLs on Windows, we don't want to treat the drive letter and - // colon as part of the path for relative file resolution when the - // incoming URL does not provide a drive spec. We save the true path - // beginning so we can fix it up after we are done. - int basePathBegin = baseParsed.path.begin(); -#if OS(WINDOWS) - if (baseIsFile) { - basePathBegin = CopyBaseDriveSpecIfNecessary(baseURL, baseParsed.path.begin(), baseParsed.path.end(), - relativeURL, relativeComponent.begin(), relativeComponent.end(), - output); - // Now the output looks like either "file://" or "file:///C:" - // and we can start appending the rest of the path. |basePathBegin| - // points to the character in the base that comes next. - } -#endif // OS(WINDOWS) - - if (URLParser::isURLSlash(relativeURL[path.begin()])) { - // Easy case: the path is an absolute path on the server, so we can - // just replace everything from the path on with the new versions. - // Since the input should be canonical hierarchical URL, we should - // always have a path. - success &= CanonicalizePath(relativeURL, path, - output, &outputParsed->path); - } else { - // Relative path, replace the query, and reference. We take the - // original path with the file part stripped, and append the new path. - // The canonicalizer will take care of resolving ".." and "." - int pathBegin = output.length(); - CopyToLastSlash(baseURL, basePathBegin, baseParsed.path.end(), - output); - success &= CanonicalizePartialPath(relativeURL, path, pathBegin, - output); - outputParsed->path = URLComponent::fromRange(pathBegin, output.length()); - - // Copy the rest of the stuff after the path from the relative path. - } - - // Finish with the query and reference part (these can't fail). - CanonicalizeQuery(relativeURL, query, queryConverter, output, &outputParsed->query); - canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); - - // Fix the path beginning to add back the "C:" we may have written above. - outputParsed->path = URLComponent::fromRange(truePathBegin, - outputParsed->path.end()); - return success; - } - - // If we get here, the path is unchanged: copy to output. - CopyOneComponent(baseURL, baseParsed.path, output, &outputParsed->path); - - if (query.isValid()) { - // Just the query specified, replace the query and reference (ignore - // failures for refs) - CanonicalizeQuery(relativeURL, query, queryConverter, - output, &outputParsed->query); - canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); - return success; - } - - // If we get here, the query is unchanged: copy to output. Note that the - // range of the query parameter doesn't include the question mark, so we - // have to add it manually if there is a component. - if (baseParsed.query.isValid()) - output.append('?'); - CopyOneComponent(baseURL, baseParsed.query, output, &outputParsed->query); - - if (ref.isValid()) { - // Just the reference specified: replace it (ignoring failures). - canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); - return success; - } - - // We should always have something to do in this function, the caller checks - // that some component is being replaced. - ASSERT_NOT_REACHED(); - return success; -} - -// Resolves a relative URL that contains a host. Typically, these will -// be of the form "//www.apple.com/foo/bar?baz#fragment" and the only thing which -// should be kept from the original URL is the scheme. -template<typename CHAR> -bool doResolveRelativeHost(const char* baseURL, - const URLSegments& baseParsed, - const CHAR* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - // Parse the relative URL, just like we would for anything following a - // scheme. - URLSegments relativeParsed; // Everything but the scheme is valid. - URLParser::parseAfterScheme(&relativeURL[relativeComponent.begin()], - relativeComponent.length(), relativeComponent.begin(), - relativeParsed); - - // Now we can just use the replacement function to replace all the necessary - // parts of the old URL with the new one. - Replacements<CHAR> replacements; - replacements.SetUsername(relativeURL, relativeParsed.username); - replacements.SetPassword(relativeURL, relativeParsed.password); - replacements.SetHost(relativeURL, relativeParsed.host); - replacements.SetPort(relativeURL, relativeParsed.port); - replacements.SetPath(relativeURL, relativeParsed.path); - replacements.SetQuery(relativeURL, relativeParsed.query); - replacements.SetRef(relativeURL, relativeParsed.fragment); - - return ReplaceStandardURL(baseURL, baseParsed, replacements, - queryConverter, output, outputParsed); -} - -// Resolves a relative URL that happens to be an absolute file path. Examples -// include: "//hostname/path", "/c:/foo", and "//hostname/c:/foo". -template<typename CharacterType> -bool doResolveAbsoluteFile(const CharacterType* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - // Parse the file URL. The file URl parsing function uses the same logic - // as we do for determining if the file is absolute, in which case it will - // not bother to look for a scheme. - URLSegments relativeParsed; - URLParser::ParseFileURL(&relativeURL[relativeComponent.begin()], - relativeComponent.length(), &relativeParsed); - - return CanonicalizeFileURL(&relativeURL[relativeComponent.begin()], - relativeComponent.length(), relativeParsed, - queryConverter, output, &outputParsed); -} - -// TODO(brettw) treat two slashes as root like Mozilla for FTP? -template<typename CHAR> -bool doResolveRelativeURL(const char* baseURL, - const URLSegments& baseParsed, - bool baseIsFile, - const CHAR* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - // Starting point for our output parsed. We'll fix what we change. - *outputParsed = baseParsed; - - // Sanity check: the input should have a host or we'll break badly below. - // We can only resolve relative URLs with base URLs that have hosts and - // paths (even the default path of "/" is OK). - // - // We allow hosts with no length so we can handle file URLs, for example. - if (baseParsed.path.length() <= 0) { - // On error, return the input (resolving a relative URL on a non-relative - // base = the base). - int baseLength = baseParsed.length(); - for (int i = 0; i < baseLength; i++) - output.append(baseURL[i]); - return false; - } - - if (relativeComponent.length() <= 0) { - // Empty relative URL, leave unchanged, only removing the ref component. - int baseLength = baseParsed.length(); - baseLength -= baseParsed.fragment.length() + 1; - outputParsed->fragment.reset(); - output.append(baseURL, baseLength); - return true; - } - - int numSlashes = URLParser::countConsecutiveSlashes(relativeURL, relativeComponent.begin(), relativeComponent.end()); - -#if OS(WINDOWS) - // On Windows, two slashes for a file path (regardless of which direction - // they are) means that it's UNC. Two backslashes on any base scheme mean - // that it's an absolute UNC path (we use the baseIsFile flag to control - // how strict the UNC finder is). - // - // We also allow Windows absolute drive specs on any scheme (for example - // "c:\foo") like IE does. There must be no preceeding slashes in this - // case (we reject anything like "/c:/foo") because that should be treated - // as a path. For file URLs, we allow any number of slashes since that would - // be setting the path. - // - // This assumes the absolute path resolver handles absolute URLs like this - // properly. URLUtilities::DoCanonicalize does this. - int afterSlashes = relativeComponent.begin + numSlashes; - if (URLParser::doesBeginUNCPath(relativeURL, relativeComponent.begin(), relativeComponent.end(), !baseIsFile) - || ((!numSlashes || baseIsFile) && URLParser::doesBeginWindowsDriveSpec(relativeURL, afterSlashes, relativeComponent.end()))) { - return doResolveAbsoluteFile(relativeURL, relativeComponent, - queryConverter, output, *outputParsed); - } -#else - // Other platforms need explicit handling for file: URLs with multiple - // slashes because the generic scheme parsing always extracts a host, but a - // file: URL only has a host if it has exactly 2 slashes. This also - // handles the special case where the URL is only slashes, since that - // doesn't have a host part either. - if (baseIsFile && (numSlashes > 2 || numSlashes == relativeComponent.length())) { - return doResolveAbsoluteFile(relativeURL, relativeComponent, - queryConverter, output, *outputParsed); - } -#endif - - // Any other double-slashes mean that this is relative to the scheme. - if (numSlashes >= 2) { - return doResolveRelativeHost(baseURL, baseParsed, - relativeURL, relativeComponent, - queryConverter, output, outputParsed); - } - - // When we get here, we know that the relative URL is on the same host. - return doResolveRelativePath(baseURL, baseParsed, baseIsFile, - relativeURL, relativeComponent, - queryConverter, output, outputParsed); -} - -} // namespace - -bool isRelativeURL(const char* base, const URLSegments& baseParsed, - const char* fragment, int fragmentLength, - bool isBaseHierarchical, - bool& isRelative, URLComponent& relativeComponent) -{ - return doIsRelativeURL<char>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent); -} - -bool isRelativeURL(const char* base, const URLSegments& baseParsed, - const UChar* fragment, int fragmentLength, - bool isBaseHierarchical, - bool& isRelative, URLComponent& relativeComponent) -{ - return doIsRelativeURL<UChar>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent); -} - -bool resolveRelativeURL(const char* baseURL, - const URLSegments& baseParsed, - bool baseIsFile, - const char* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doResolveRelativeURL<char>(baseURL, baseParsed, baseIsFile, relativeURL, - relativeComponent, queryConverter, output, outputParsed); -} - -bool resolveRelativeURL(const char* baseURL, - const URLSegments& baseParsed, - bool baseIsFile, - const UChar* relativeURL, - const URLComponent& relativeComponent, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doResolveRelativeURL<UChar>(baseURL, baseParsed, baseIsFile, relativeURL, - relativeComponent, queryConverter, output, outputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonStdURL.cpp b/Source/WTF/wtf/url/src/URLCanonStdURL.cpp deleted file mode 100644 index 5e2dd1cea..000000000 --- a/Source/WTF/wtf/url/src/URLCanonStdURL.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Functions to canonicalize "standard" URLs, which are ones that have an -// authority section including a host name. - -#include "config.h" -#include "URLCanon.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLCanonicalizer { - -namespace { - -template<typename CHAR, typename UCHAR> -bool doCanonicalizeStandardURL(const URLComponentSource<CHAR>& source, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - // Scheme: this will append the colon. - bool success = canonicalizeScheme(source.scheme, parsed.scheme, output, outputParsed.scheme); - - // Authority (username, password, host, port) - bool haveAuthority; - if (parsed.username.isNonEmpty() || parsed.password.isValid() || parsed.host.isNonEmpty() || parsed.port.isValid()) { - haveAuthority = true; - - // Only write the authority separators when we have a scheme. - if (parsed.scheme.isValid()) - output.append("//", 2); - - // User info: the canonicalizer will handle the : and @. - success &= canonicalizeUserInfo(source.username, parsed.username, source.password, parsed.password, - output, outputParsed.username, outputParsed.password); - success &= canonicalizeHost(source.host, parsed.host, output, outputParsed.host); - - // Host must not be empty for standard URLs. - if (!parsed.host.isNonEmpty()) - success = false; - - // Port: the port canonicalizer will handle the colon. - int defaultPort = defaultPortForScheme(&output.data()[outputParsed.scheme.begin()], outputParsed.scheme.length()); - success &= canonicalizePort(source.port, parsed.port, defaultPort, output, outputParsed.port); - } else { - // No authority, clear the components. - haveAuthority = false; - outputParsed.host.reset(); - outputParsed.username.reset(); - outputParsed.password.reset(); - outputParsed.port.reset(); - success = false; // Standard URLs must have an authority. - } - - // Path - if (parsed.path.isNonEmpty()) - success &= CanonicalizePath(source.path, parsed.path, output, &outputParsed.path); - else if (haveAuthority || parsed.query.isNonEmpty() || parsed.fragment.isNonEmpty()) { - // When we have an empty path, make up a path when we have an authority - // or something following the path. The only time we allow an empty - // output path is when there is nothing else. - outputParsed.path = URLComponent(output.length(), 1); - output.append('/'); - } else - outputParsed.path.reset(); // No path at all - - // Query - CanonicalizeQuery(source.query, parsed.query, queryConverter, output, &outputParsed.query); - - // Ref: ignore failure for this, since the page can probably still be loaded. - canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); - - return success; -} - -} // namespace - - -// Returns the default port for the given canonical scheme, or PORT_UNSPECIFIED -// if the scheme is unknown. -int defaultPortForScheme(const char* scheme, int schemeLength) -{ - int defaultPort = URLParser::PORT_UNSPECIFIED; - switch (schemeLength) { - case 4: - if (!strncmp(scheme, "http", schemeLength)) - defaultPort = 80; - break; - case 5: - if (!strncmp(scheme, "https", schemeLength)) - defaultPort = 443; - break; - case 3: - if (!strncmp(scheme, "ftp", schemeLength)) - defaultPort = 21; - else if (!strncmp(scheme, "wss", schemeLength)) - defaultPort = 443; - break; - case 6: - if (!strncmp(scheme, "gopher", schemeLength)) - defaultPort = 70; - break; - case 2: - if (!strncmp(scheme, "ws", schemeLength)) - defaultPort = 80; - break; - } - return defaultPort; -} - -bool CanonicalizeStandardURL(const char* spec, - int /* specLength */, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doCanonicalizeStandardURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, queryConverter, - output, *outputParsed); -} - -bool CanonicalizeStandardURL(const UChar* spec, - int /* specLength */, - const URLSegments& parsed, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doCanonicalizeStandardURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, queryConverter, - output, *outputParsed); -} - -// It might be nice in the future to optimize this so unchanged components don't -// need to be recanonicalized. This is especially true since the common case for -// ReplaceComponents is removing things we don't want, like reference fragments -// and usernames. These cases can become more efficient if we can assume the -// rest of the URL is OK with these removed (or only the modified parts -// recanonicalized). This would be much more complex to implement, however. -// -// You would also need to update DoReplaceComponents in URLUtilities.cc which -// relies on this re-checking everything (see the comment there for why). -bool ReplaceStandardURL(const char* base, - const URLSegments& baseParsed, - const Replacements<char>& replacements, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupOverrideComponents(base, replacements, &source, &parsed); - return doCanonicalizeStandardURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); -} - -// For 16-bit replacements, we turn all the replacements into UTF-8 so the -// regular codepath can be used. -bool ReplaceStandardURL(const char* base, - const URLSegments& baseParsed, - const Replacements<UChar>& replacements, - URLQueryCharsetConverter* queryConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - RawURLBuffer<char> utf8; - URLComponentSource<char> source(base); - URLSegments parsed(baseParsed); - SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); - return doCanonicalizeStandardURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); -} - -} // namespace URLCanonicalizer - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCharacterTypes.cpp b/Source/WTF/wtf/url/src/URLCharacterTypes.cpp deleted file mode 100644 index 21dd22fcc..000000000 --- a/Source/WTF/wtf/url/src/URLCharacterTypes.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 | ComponentCharacter, // 0x21 ! - InvalidCharacter, // 0x22 " - InvalidCharacter, // 0x23 # (invalid in query since it marks the ref) - QueryCharacter | UserInfoCharacter, // 0x24 $ - QueryCharacter | UserInfoCharacter, // 0x25 % - QueryCharacter | UserInfoCharacter, // 0x26 & - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x27 ' - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x28 ( - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x29 ) - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x2a * - QueryCharacter | UserInfoCharacter, // 0x2b + - QueryCharacter | UserInfoCharacter, // 0x2c , - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x2d - - QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x2e . - QueryCharacter, // 0x2f / - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x30 0 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x31 1 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x32 2 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x33 3 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x34 4 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x35 5 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x36 6 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x37 7 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | ComponentCharacter, // 0x38 8 - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | ComponentCharacter, // 0x39 9 - QueryCharacter, // 0x3a : - QueryCharacter, // 0x3b ; - InvalidCharacter, // 0x3c < (Try to prevent certain types of XSS.) - QueryCharacter, // 0x3d = - InvalidCharacter, // 0x3e > (Try to prevent certain types of XSS.) - QueryCharacter, // 0x3f ? - QueryCharacter, // 0x40 @ - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x41 A - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x42 B - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x43 C - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x44 D - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x45 E - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x46 F - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x47 G - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x48 H - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x49 I - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4a J - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4b K - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4c L - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4d M - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4e N - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4f O - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x50 P - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x51 Q - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x52 R - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x53 S - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x54 T - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x55 U - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x56 V - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x57 W - QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x58 X - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x59 Y - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x5a Z - QueryCharacter, // 0x5b [ - QueryCharacter, // 0x5c '\' - QueryCharacter, // 0x5d ] - QueryCharacter, // 0x5e ^ - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x5f _ - QueryCharacter, // 0x60 ` - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x61 a - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x62 b - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x63 c - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x64 d - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x65 e - QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x66 f - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x67 g - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x68 h - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x69 i - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6a j - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6b k - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6c l - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6d m - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6e n - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6f o - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x70 p - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x71 q - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x72 r - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x73 s - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x74 t - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x75 u - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x76 v - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x77 w - QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x78 x - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x79 y - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x7a z - QueryCharacter, // 0x7b { - QueryCharacter, // 0x7c | - QueryCharacter, // 0x7d } - QueryCharacter | UserInfoCharacter | ComponentCharacter, // 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/WTF/wtf/url/src/URLCharacterTypes.h b/Source/WTF/wtf/url/src/URLCharacterTypes.h deleted file mode 100644 index 6652105e8..000000000 --- a/Source/WTF/wtf/url/src/URLCharacterTypes.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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: - enum CharacterTypes { - InvalidCharacter = 0, - QueryCharacter = 1 << 0, - UserInfoCharacter = 1 << 1, - IPv4Character = 1 << 2, - HexadecimalCharacter = 1 << 3, - DecimalCharacter = 1 << 4, - OctalCharacter = 1 << 5, - ComponentCharacter = 1 << 6, - }; - - static inline bool isComponentChar(unsigned char character) { return isCharacterOfType(character, ComponentCharacter); } - static inline bool isHexChar(unsigned char character) { return isCharacterOfType(character, HexadecimalCharacter); } - static inline bool isIPv4Char(unsigned char character) { return isCharacterOfType(character, IPv4Character); } - static inline bool isQueryChar(unsigned char character) { return isCharacterOfType(character, QueryCharacter); } - - static inline bool isCharacterOfType(unsigned char HexCharacter, CharacterTypes type) - { - return !!(characterTypeTable[HexCharacter] & type); - } - -private: - static const unsigned char characterTypeTable[0x100]; -}; - -} - -#endif // USE(WTFURL) - -#endif // URLCharacterTypes_h diff --git a/Source/WTF/wtf/url/src/URLComponent.h b/Source/WTF/wtf/url/src/URLComponent.h deleted file mode 100644 index 86ae05a74..000000000 --- a/Source/WTF/wtf/url/src/URLComponent.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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; } - void moveBy(int offset) { m_begin += offset; } - - 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/WTF/wtf/url/src/URLFile.h b/Source/WTF/wtf/url/src/URLFile.h deleted file mode 100644 index 48b12ebdf..000000000 --- a/Source/WTF/wtf/url/src/URLFile.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Provides shared functions used by the internals of the parser and -// canonicalizer for file URLs. Do not use outside of these modules. - -#ifndef URLFile_h -#define URLFile_h - -#include "URLParseInternal.h" -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLParser { - -#if OS(WINDOWS) -// We allow both "c:" and "c|" as drive identifiers. -inline bool isWindowsDriveSeparator(UChar character) -{ - return character == ':' || character == '|'; -} -inline bool isWindowsDriveLetter(UChar character) -{ - return (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z'); -} -#endif // OS(WINDOWS) - -// Returns the index of the next slash in the input after the given index, or -// specLength if the end of the input is reached. -template<typename CharacterType> -inline int findNextSlash(const CharacterType* spec, int beginIndex, int specLength) -{ - int idx = beginIndex; - while (idx < specLength && !isURLSlash(spec[idx])) - ++idx; - return idx; -} - -#if OS(WINDOWS) -// Returns true if the startOffset in the given spec looks like it begins a -// drive spec, for example "c:". This function explicitly handles startOffset -// values that are equal to or larger than the specLength to simplify callers. -// -// If this returns true, the spec is guaranteed to have a valid drive letter -// plus a colon starting at |startOffset|. -template<typename CharacterType> -inline bool doesBeginWindowsDriveSpec(const CharacterType* spec, int startOffset, int specLength) -{ - int remainingLength = specLength - startOffset; - if (remainingLength < 2) - return false; // Not enough room. - if (!isWindowsDriveLetter(spec[startOffset])) - return false; // Doesn't start with a valid drive letter. - if (!isWindowsDriveSeparator(spec[startOffset + 1])) - return false; // Isn't followed with a drive separator. - return true; -} - -// Returns true if the startOffset in the given text looks like it begins a -// UNC path, for example "\\". This function explicitly handles startOffset -// values that are equal to or larger than the specLength to simplify callers. -// -// When strictSlashes is set, this function will only accept backslashes as is -// standard for Windows. Otherwise, it will accept forward slashes as well -// which we use for a lot of URL handling. -template<typename CharacterType> -inline bool doesBeginUNCPath(const CharacterType* text, int startOffset, int length, bool strictSlashes) -{ - int remainingLength = length - startOffset; - if (remainingLength < 2) - return false; - - if (strictSlashes) - return text[startOffset] == '\\' && text[startOffset + 1] == '\\'; - return isURLSlash(text[startOffset]) && isURLSlash(text[startOffset + 1]); -} -#endif // OS(WINDOWS) - -} // namespace URLParser - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLFile_h diff --git a/Source/WTF/wtf/url/src/URLParse.cpp b/Source/WTF/wtf/url/src/URLParse.cpp deleted file mode 100644 index 91e65b423..000000000 --- a/Source/WTF/wtf/url/src/URLParse.cpp +++ /dev/null @@ -1,780 +0,0 @@ -/* Based on nsURLParsers.cc from Mozilla - * ------------------------------------- - * Copyright (C) 1998 Netscape Communications Corporation. - * Copyright 2012, Google Inc. All rights reserved. - * Copyright (C) 2012 Apple Inc. All rights reserved. - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Darin Fisher (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - */ - -#include "config.h" -#include "URLParse.h" - -#include "URLParseInternal.h" -#include "URLUtil.h" -#include "URLUtilInternal.h" -#include <stdlib.h> -#include <wtf/ASCIICType.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLParser { - -namespace { - -// 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. -template<typename CharacterType> -int findNextAuthorityTerminator(const CharacterType* spec, int startOffset, int specLength) -{ - for (int i = startOffset; i < specLength; i++) { - if (IsAuthorityTerminator(spec[i])) - return i; - } - return specLength; // Not found. -} - -template<typename CharacterType> -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.end()); - } else { - // No separator, treat everything as the username - username = user; - password = URLComponent(); - } -} - -template<typename CharacterType> -void parseServerInfo(const CharacterType* spec, const URLComponent& serverInfo, URLComponent& hostname, URLComponent& port) -{ - if (!serverInfo.length()) { - // No server info, host name is empty. - hostname = URLComponent(); - port = URLComponent(); - 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; - } - } - - if (colon > ipv6Terminator) { - // Found a port number: <hostname>:<port> - hostname = URLComponent::fromRange(serverInfo.begin(), colon); - if (!hostname.length()) - hostname.reset(); - port = URLComponent::fromRange(colon + 1, serverInfo.end()); - } else { - // No port: <hostname> - hostname = serverInfo; - port = URLComponent(); - } -} - -// Given an already-identified auth section, breaks it into its consituent -// 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. -template<typename CharacterType> -void doParseAuthority(const CharacterType* spec, const URLComponent& authority, URLComponent& username, URLComponent& password, URLComponent& hostname, URLComponent& port) -{ - ASSERT_WITH_MESSAGE(authority.isValid(), "We should always get an authority"); - if (!authority.length()) { - username = URLComponent(); - password = URLComponent(); - hostname = URLComponent(); - port = URLComponent(); - return; - } - - // Search backwards for @, which is the separator between the user info and - // the server info. - int i = authority.end() - 1; - while (i > authority.begin() && spec[i] != '@') - --i; - - if (spec[i] == '@') { - // Found user info: <user-info>@<server-info> - parseUserInfo(spec, URLComponent(authority.begin(), i - authority.begin()), username, password); - parseServerInfo(spec, URLComponent::fromRange(i + 1, authority.end()), hostname, port); - } else { - // No user info, everything is server info. - username = URLComponent(); - password = URLComponent(); - parseServerInfo(spec, authority, hostname, port); - } -} - -template<typename CharacterType> -void parsePath(const CharacterType* spec, const URLComponent& hierarchicalidentifiers, URLComponent& resourcePath, URLComponent& query, URLComponent& fragment) -{ - // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<ref> - - // Special case when there is no path. - if (hierarchicalidentifiers.length() == -1) { - resourcePath = URLComponent(); - query = URLComponent(); - fragment = URLComponent(); - return; - } - ASSERT_WITH_MESSAGE(hierarchicalidentifiers.length() > 0, "We should never have 0 length paths"); - - // Search for first occurrence of either ? or #. - int pathEnd = hierarchicalidentifiers.end(); - - int querySeparator = -1; // Index of the '?' - int fragmentSeparator = -1; // Index of the '#' - for (int i = hierarchicalidentifiers.begin(); i < pathEnd; ++i) { - switch (spec[i]) { - case '?': - // Only match the query string if it precedes the reference fragment - // and when we haven't found one already. - if (fragmentSeparator < 0 && querySeparator < 0) - querySeparator = i; - break; - case '#': - // Record the first # sign only. - if (fragmentSeparator < 0) - fragmentSeparator = i; - break; - } - } - - // Markers pointing to the character after each of these corresponding - // components. The code below words from the end back to the beginning, - // and will update these indices as it finds components that exist. - int resourcePathEnd = -1; - int queryEnd = -1; - - // Ref fragment: from the # to the end of the path. - if (fragmentSeparator >= 0) { - resourcePathEnd = queryEnd = fragmentSeparator; - fragment = URLComponent::fromRange(fragmentSeparator + 1, pathEnd); - } else { - resourcePathEnd = queryEnd = pathEnd; - fragment = URLComponent(); - } - - // Query fragment: everything from the ? to the next boundary (either the end - // of the path or the ref fragment). - if (querySeparator >= 0) { - resourcePathEnd = querySeparator; - query = URLComponent::fromRange(querySeparator + 1, queryEnd); - } else - query = URLComponent(); - - // File path: treat an empty file path as no file path. - if (resourcePathEnd != hierarchicalidentifiers.begin()) - resourcePath = URLComponent::fromRange(hierarchicalidentifiers.begin(), resourcePathEnd); - else - resourcePath = URLComponent(); -} - -template<typename CharacterType> -bool doExtractScheme(const CharacterType* url, int urlLength, URLComponent& scheme) -{ - // Skip leading whitespace and control characters. - int begin = 0; - while (begin < urlLength && shouldTrimFromURL(url[begin])) - ++begin; - - if (begin == urlLength) - return false; // Input is empty or all whitespace. - - // Find the first colon character. - for (int i = begin; i < urlLength; ++i) { - if (url[i] == ':') { - scheme = URLComponent::fromRange(begin, i); - return true; - } - } - return false; // No colon found: no scheme -} - -// Fills in all members of the Parsed structure except for the scheme. -// -// |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. -// -// Compatability data points. I list "host", "path" extracted: -// Input IE6 Firefox Us -// ----- -------------- -------------- -------------- -// http://foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" -// http:foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" -// http:/foo.com/ fail(*) "foo.com", "/" "foo.com", "/" -// http:\foo.com/ fail(*) "\foo.com", "/"(fail) "foo.com", "/" -// http:////foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" -// -// (*) Interestingly, although IE fails to load these URLs, its history -// canonicalizer handles them, meaning if you've been to the corresponding -// "http://foo.com/" link, it will be colored. -template <typename CharacterType> -void doParseAfterScheme(const CharacterType* spec, int specLength, int afterScheme, URLSegments& parsed) -{ - int slashesCount = countConsecutiveSlashes(spec, afterScheme, specLength); - int afterSlashes = afterScheme + slashesCount; - - // 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 endAuth = findNextAuthorityTerminator(spec, afterSlashes, specLength); - authority = URLComponent::fromRange(afterSlashes, endAuth); - - if (endAuth == specLength) // No beginning of path found. - fullPath = URLComponent(); - else // Everything starting from the slash to the end is the path. - fullPath = URLComponent::fromRange(endAuth, specLength); - - // Now parse those two sub-parts. - doParseAuthority(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. -template<typename CharacterType> -void doParseStandardURL(const CharacterType* spec, int specLength, URLSegments& parsed) -{ - ASSERT(specLength >= 0); - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - int afterScheme = -1; - if (doExtractScheme(spec, specLength, parsed.scheme)) - afterScheme = parsed.scheme.end() + 1; // Skip past the colon. - else { - // Say there's no scheme when there is no 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; - } - doParseAfterScheme(spec, specLength, afterScheme, parsed); -} - -template<typename CharacterType> -void doParseFileSystemURL(const CharacterType* spec, int specLength, URLSegments& parsed) -{ - ASSERT(specLength >= 0); - - // Get the unused parts of the URL out of the way. - parsed.username.reset(); - parsed.password.reset(); - parsed.host.reset(); - parsed.port.reset(); - parsed.path.reset(); // May use this; reset for convenience. - parsed.fragment.reset(); // May use this; reset for convenience. - parsed.query.reset(); // May use this; reset for convenience. - parsed.clearInnerURLSegments(); // 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(); - return; - } - - int innerStart = -1; - - // Extract the scheme. We also handle the case where there is no scheme. - if (doExtractScheme(&spec[begin], specLength - begin, parsed.scheme)) { - // Offset the results since we gave ExtractScheme a substring. - parsed.scheme.moveBy(begin); - - if (parsed.scheme.end() == specLength - 1) - return; - - innerStart = parsed.scheme.end() + 1; - } else { - // No scheme found; that's not valid for filesystem URLs. - parsed.scheme.reset(); - return; - } - - URLComponent innerScheme; - const CharacterType* innerSpec = &spec[innerStart]; - int innerSpecLength = specLength - innerStart; - - if (doExtractScheme(innerSpec, innerSpecLength, innerScheme)) { - // Offset the results since we gave ExtractScheme a substring. - innerScheme.moveBy(innerStart); - - if (innerScheme.end() == specLength - 1) - return; - } else { - // No scheme found; that's not valid for filesystem URLs. - // The best we can do is return "filesystem://". - return; - } - - URLSegments innerParsed; - if (URLUtilities::CompareSchemeComponent(spec, innerScheme, URLUtilities::kFileScheme)) { - // File URLs are special. - ParseFileURL(innerSpec, innerSpecLength, &innerParsed); - } else if (URLUtilities::CompareSchemeComponent(spec, innerScheme, URLUtilities::kFileSystemScheme)) { - // Filesystem URLs don't nest. - return; - } else if (URLUtilities::isStandard(spec, innerScheme)) { - // All "normal" URLs. - doParseStandardURL(innerSpec, innerSpecLength, innerParsed); - } else - return; - - // All members of innerParsed need to be offset by innerStart. - // If we had any scheme that supported nesting more than one level deep, - // we'd have to recurse into the innerParsed's innerParsed when - // adjusting by innerStart. - innerParsed.moveFromComponentBy(URLSegments::Scheme, innerStart); - - // Query and ref move from innerParsed to parsed. - parsed.query = innerParsed.query; - innerParsed.query.reset(); - parsed.fragment = innerParsed.fragment; - innerParsed.fragment.reset(); - - parsed.setInnerURLSegments(innerParsed); - if (!innerParsed.scheme.isValid() || !innerParsed.path.isValid() || innerParsed.innerURLSegments()) - return; - - // The path in innerParsed should start with a slash, then have a filesystem - // type followed by a slash. From the first slash up to but excluding the - // second should be what it keeps; the rest goes to parsed. If the path ends - // before the second slash, it's still pretty clear what the user meant, so - // we'll let that through. - if (!isURLSlash(spec[innerParsed.path.begin()])) - return; - - int innerPathEnd = innerParsed.path.begin() + 1; // skip the leading slash - while (innerPathEnd < specLength && !isURLSlash(spec[innerPathEnd])) - ++innerPathEnd; - parsed.path.setBegin(innerPathEnd); - int newInnerPathLength = innerPathEnd - innerParsed.path.begin(); - parsed.path.setLength(innerParsed.path.length() - newInnerPathLength); - innerParsed.path.setLength(newInnerPathLength); - parsed.setInnerURLSegments(innerParsed); -} - -// Initializes a path URL which is merely a scheme followed by a path. Examples -// include "about:foo" and "javascript:alert('bar');" -template<typename CharacterType> -void doParsePathURL(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. - 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.moveBy(begin); - - // For compatability 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); - } -} - -template<typename CharacterType> -void doParseMailtoURL(const CharacterType* spec, int specLength, URLSegments& parsed) -{ - 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.moveBy(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 compatability 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); -} - -// Converts a port number in a string to an integer. We'd like to just call -// sscanf but our input is not null-terminated, which sscanf requires. Instead, -// we copy the digits to a small stack buffer (since we know the maximum number -// of digits in a valid port number) that we can null terminate. -template<typename CharacterType> -int doParsePort(const CharacterType* spec, const URLComponent& component) -{ - // Easy success case when there is no port. - const int kMaxDigits = 5; - if (!component.isNonEmpty()) - return PORT_UNSPECIFIED; - - // Skip over any leading 0s. - URLComponent digitComponent(component.end(), 0); - for (int i = 0; i < component.length(); i++) { - if (spec[component.begin() + i] != '0') { - digitComponent = URLComponent::fromRange(component.begin() + i, component.end()); - break; - } - } - if (!digitComponent.length()) - return 0; // All digits were 0. - - // Verify we don't have too many digits (we'll be copying to our buffer so - // we need to double-check). - if (digitComponent.length() > kMaxDigits) - return PORT_INVALID; - - // Copy valid digits to the buffer. - char digits[kMaxDigits + 1]; // +1 for null terminator - for (int i = 0; i < digitComponent.length(); i++) { - CharacterType ch = spec[digitComponent.begin() + i]; - if (!isASCIIDigit(ch)) { - // Invalid port digit, fail. - return PORT_INVALID; - } - digits[i] = static_cast<char>(ch); - } - - // Null-terminate the string and convert to integer. Since we guarantee - // only digits, atoi's lack of error handling is OK. - digits[digitComponent.length()] = 0; - int port = atoi(digits); - if (port > 65535) - return PORT_INVALID; // Out of range. - return port; -} - -template<typename CharacterType> -void doExtractFileName(const CharacterType* spec, const URLComponent& path, URLComponent& fileName) -{ - // Handle empty paths: they have no file names. - if (!path.isNonEmpty()) { - fileName = URLComponent(); - 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. The path should start with a slash, so we don't need to check - // the first one. - 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); - return; -} - -template<typename CharacterType> -bool doExtractQueryKeyValue(const CharacterType* spec, URLComponent& query, URLComponent& key, URLComponent& value) -{ - if (!query.isNonEmpty()) - 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; -} - -} // namespace - -bool ExtractScheme(const char* url, int urlLength, URLComponent* scheme) -{ - return doExtractScheme(url, urlLength, *scheme); -} - -bool ExtractScheme(const UChar* url, int urlLength, URLComponent* scheme) -{ - return doExtractScheme(url, urlLength, *scheme); -} - -// This handles everything that may be an authority terminator, including -// backslash. For special backslash handling see DoParseAfterScheme. -bool IsAuthorityTerminator(UChar character) -{ - return isURLSlash(character) || character == '?' || character == '#'; -} - -void ExtractFileName(const char* url, const URLComponent& path, URLComponent* fileName) -{ - doExtractFileName(url, path, *fileName); -} - -void ExtractFileName(const UChar* url, const URLComponent& path, URLComponent* fileName) -{ - doExtractFileName(url, path, *fileName); -} - -bool ExtractQueryKeyValue(const char* url, URLComponent* query, URLComponent* key, URLComponent* value) -{ - return doExtractQueryKeyValue(url, *query, *key, *value); -} - -bool ExtractQueryKeyValue(const UChar* url, URLComponent* query, URLComponent* key, URLComponent* value) -{ - return doExtractQueryKeyValue(url, *query, *key, *value); -} - -void ParseAuthority(const char* spec, const URLComponent& auth, URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber) -{ - doParseAuthority(spec, auth, *username, *password, *hostname, *portNumber); -} - -void ParseAuthority(const UChar* spec, const URLComponent& auth, URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber) -{ - doParseAuthority(spec, auth, *username, *password, *hostname, *portNumber); -} - -int ParsePort(const char* url, const URLComponent& port) -{ - return doParsePort(url, port); -} - -int ParsePort(const UChar* url, const URLComponent& port) -{ - return doParsePort(url, port); -} - -void ParseStandardURL(const char* url, int urlLength, URLSegments* parsed) -{ - doParseStandardURL(url, urlLength, *parsed); -} - -void ParseStandardURL(const UChar* url, int urlLength, URLSegments* parsed) -{ - doParseStandardURL(url, urlLength, *parsed); -} - -void ParsePathURL(const char* url, int urlLength, URLSegments* parsed) -{ - doParsePathURL(url, urlLength, *parsed); -} - -void ParsePathURL(const UChar* url, int urlLength, URLSegments* parsed) -{ - doParsePathURL(url, urlLength, *parsed); -} - -void ParseFileSystemURL(const char* url, int urlLength, URLSegments* parsed) -{ - doParseFileSystemURL(url, urlLength, *parsed); -} - -void ParseFileSystemURL(const UChar* url, int urlLength, URLSegments* parsed) -{ - doParseFileSystemURL(url, urlLength, *parsed); -} - -void ParseMailtoURL(const char* url, int urlLength, URLSegments* parsed) -{ - doParseMailtoURL(url, urlLength, *parsed); -} - -void ParseMailtoURL(const UChar* url, int urlLength, URLSegments* parsed) -{ - doParseMailtoURL(url, urlLength, *parsed); -} - -void parsePathInternal(const char* spec, const URLComponent& path, URLComponent* filepath, URLComponent* query, URLComponent* fragment) -{ - parsePath(spec, path, *filepath, *query, *fragment); -} - -void parsePathInternal(const UChar* spec, const URLComponent& path, URLComponent* filepath, URLComponent* query, URLComponent* fragment) -{ - parsePath(spec, path, *filepath, *query, *fragment); -} - -void parseAfterScheme(const char* spec, int specLength, int afterScheme, URLSegments& parsed) -{ - doParseAfterScheme(spec, specLength, afterScheme, parsed); -} - -void parseAfterScheme(const UChar* spec, int specLength, int afterScheme, URLSegments& parsed) -{ - doParseAfterScheme(spec, specLength, afterScheme, parsed); -} - -} // namespace URLParser - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLParse.h b/Source/WTF/wtf/url/src/URLParse.h deleted file mode 100644 index c97b10a91..000000000 --- a/Source/WTF/wtf/url/src/URLParse.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 URLParse_h -#define URLParse_h - -#include "URLComponent.h" -#include "URLSegments.h" -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLParser { - -// Initialization functions --------------------------------------------------- -// -// These functions parse the given URL, filling in all of the structure's -// components. These functions can not fail, they will always do their best -// at interpreting the input given. -// -// The string length of the URL MUST be specified, we do not check for NULLs -// at any point in the process, and will actually handle embedded NULLs. -// -// IMPORTANT: These functions do NOT hang on to the given pointer or copy it -// in any way. See the comment above the struct. -// -// The 8-bit versions require UTF-8 encoding. - -// StandardURL is for when the scheme is known to be one that has an -// authority (host) like "http". This function will not handle weird ones -// like "about:" and "javascript:", or do the right thing for "file:" URLs. -void ParseStandardURL(const char* url, int urlLength, URLSegments* parsed); -void ParseStandardURL(const UChar* url, int urlLength, URLSegments* parsed); - -// PathURL is for when the scheme is known not to have an authority (host) -// section but that aren't file URLs either. The scheme is parsed, and -// everything after the scheme is considered as the path. This is used for -// things like "about:" and "javascript:" -void ParsePathURL(const char* url, int urlLength, URLSegments* parsed); -void ParsePathURL(const UChar* url, int urlLength, URLSegments* parsed); - -// FileURL is for file URLs. There are some special rules for interpreting -// these. -void ParseFileURL(const char* url, int urlLength, URLSegments* parsed); -void ParseFileURL(const UChar* url, int urlLength, URLSegments* parsed); - -// Filesystem URLs are structured differently than other URLs. -void ParseFileSystemURL(const char* url, int urlLength, URLSegments* parsed); -void ParseFileSystemURL(const UChar* url, int urlLength, URLSegments* parsed); - -// MailtoURL is for mailto: urls. They are made up scheme,path,query -void ParseMailtoURL(const char* url, int urlLength, URLSegments* parsed); -void ParseMailtoURL(const UChar* url, int urlLength, URLSegments* parsed); - -// Helper functions ----------------------------------------------------------- - -// Locates the scheme according to the URL parser's rules. This function is -// designed so the caller can find the scheme and call the correct Init* -// function according to their known scheme types. -// -// It also does not perform any validation on the scheme. -// -// This function will return true if the scheme is found and will put the -// scheme's range into *scheme. False means no scheme could be found. Note -// that a URL beginning with a colon has a scheme, but it is empty, so this -// function will return true but *scheme will = (0,0). -// -// The scheme is found by skipping spaces and control characters at the -// beginning, and taking everything from there to the first colon to be the -// scheme. The character at scheme.end() will be the colon (we may enhance -// this to handle full width colons or something, so don't count on the -// actual character value). The character at scheme.end()+1 will be the -// beginning of the rest of the URL, be it the authority or the path (or the -// end of the string). -// -// The 8-bit version requires UTF-8 encoding. -bool ExtractScheme(const char* url, int urlLength, URLComponent* scheme); -bool ExtractScheme(const UChar* url, int urlLength, URLComponent* scheme); - -// Returns true if ch is a character that terminates the authority segment of a URL. -bool IsAuthorityTerminator(UChar); - -// Does a best effort parse of input |spec|, in range |auth|. If a particular -// component is not found, it will be set to invalid. -void ParseAuthority(const char* spec, const URLComponent& auth, - URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber); -void ParseAuthority(const UChar* spec, const URLComponent& auth, - URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber); - -// Computes the integer port value from the given port component. The port -// component should have been identified by one of the init functions on -// |Parsed| for the given input url. -// -// The return value will be a positive integer between 0 and 64K, or one of -// the two special values below. -enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 }; -int ParsePort(const char* url, const URLComponent& port); -int ParsePort(const UChar* url, const URLComponent& port); - -// Extracts the range of the file name in the given url. The path must -// already have been computed by the parse function, and the matching URL -// and extracted path are provided to this function. The filename is -// defined as being everything from the last slash/backslash of the path -// to the end of the path. -// -// The file name will be empty if the path is empty or there is nothing -// following the last slash. -// -// The 8-bit version requires UTF-8 encoding. -void ExtractFileName(const char* url, const URLComponent& path, URLComponent* fileName); -void ExtractFileName(const UChar* url, const URLComponent& path, URLComponent* fileName); - -// Extract the first key/value from the range defined by |*query|. Updates -// |*query| to start at the end of the extracted key/value pair. This is -// designed for use in a loop: you can keep calling it with the same query -// object and it will iterate over all items in the query. -// -// Some key/value pairs may have the key, the value, or both be empty (for -// example, the query string "?&"). These will be returned. Note that an empty -// last parameter "foo.com?" or foo.com?a&" will not be returned, this case -// is the same as "done." -// -// The initial query component should not include the '?' (this is the default -// for parsed URLs). -// -// If no key/value are found |*key| and |*value| will be unchanged and it will -// return false. -bool ExtractQueryKeyValue(const char* url, URLComponent* query, URLComponent* key, URLComponent* value); -bool ExtractQueryKeyValue(const UChar* url, URLComponent* query, URLComponent* key, URLComponent* value); - -} // namespace URLParser - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLParse_h diff --git a/Source/WTF/wtf/url/src/URLParseFile.cpp b/Source/WTF/wtf/url/src/URLParseFile.cpp deleted file mode 100644 index 911821991..000000000 --- a/Source/WTF/wtf/url/src/URLParseFile.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLParse.h" - -#include "URLFile.h" -#include "URLParseInternal.h" - -// Interesting IE file:isms... -// -// INPUT OUTPUT -// ========================= ============================== -// file:/foo/bar file:///foo/bar -// The result here seems totally invalid!?!? This isn't UNC. -// -// file:/ -// file:// or any other number of slashes -// IE6 doesn't do anything at all if you click on this link. No error: -// nothing. IE6's history system seems to always color this link, so I'm -// guessing that it maps internally to the empty URL. -// -// C:\ file:///C:/ -// When on a file: URL source page, this link will work. When over HTTP, -// the file: URL will appear in the status bar but the link will not work -// (security restriction for all file URLs). -// -// file:foo/ file:foo/ (invalid?!?!?) -// file:/foo/ file:///foo/ (invalid?!?!?) -// file://foo/ file://foo/ (UNC to server "foo") -// file:///foo/ file:///foo/ (invalid, seems to be a file) -// file:////foo/ file://foo/ (UNC to server "foo") -// Any more than four slashes is also treated as UNC. -// -// file:C:/ file://C:/ -// file:/C:/ file://C:/ -// The number of slashes after "file:" don't matter if the thing following -// it looks like an absolute drive path. Also, slashes and backslashes are -// equally valid here. - -#if USE(WTFURL) - -namespace WTF { - -namespace URLParser { - -namespace { - -// A subcomponent of DoInitFileURL, the input of this function should be a UNC -// path name, with the index of the first character after the slashes following -// the scheme given in |afterSlashes|. This will initialize the host, path, -// query, and ref, and leave the other output components untouched -// (DoInitFileURL handles these for us). -template<typename CharacterType> -void doParseUNC(const CharacterType* spec, int afterSlashes, int specLength, URLSegments& parsed) -{ - int nextSlash = findNextSlash(spec, afterSlashes, specLength); - if (nextSlash == specLength) { - // No additional slash found, as in "file://foo", treat the text as the - // host with no path (this will end up being UNC to server "foo"). - int hostLength = specLength - afterSlashes; - if (hostLength) - parsed.host = URLComponent(afterSlashes, hostLength); - else - parsed.host.reset(); - parsed.path.reset(); - return; - } - -#if OS(WINDOWS) - // See if we have something that looks like a path following the first - // component. As in "file://localhost/c:/", we get "c:/" out. We want to - // treat this as a having no host but the path given. Works on Windows only. - if (doesBeginWindowsDriveSpec(spec, nextSlash + 1, specLength)) { - parsed.host.reset(); - parsePathInternal(spec, MakeRange(nextSlash, specLength), - &parsed.path, &parsed.query, &parsed.ref); - return; - } -#endif - - // Otherwise, everything up until that first slash we found is the host name, - // which will end up being the UNC host. For example "file://foo/bar.txt" - // will get a server name of "foo" and a path of "/bar". Later, on Windows, - // this should be treated as the filename "\\foo\bar.txt" in proper UNC - // notation. - int hostLength = nextSlash - afterSlashes; - if (hostLength) - parsed.host = URLComponent::fromRange(afterSlashes, nextSlash); - else - parsed.host.reset(); - if (nextSlash < specLength) { - parsePathInternal(spec, URLComponent::fromRange(nextSlash, specLength), - &parsed.path, &parsed.query, &parsed.fragment); - } else - parsed.path.reset(); -} - -// A subcomponent of DoParseFileURL, the input should be a local file, with the -// beginning of the path indicated by the index in |pathBegin|. This will -// initialize the host, path, query, and ref, and leave the other output -// components untouched (DoInitFileURL handles these for us). -template<typename CharacterType> -void doParseLocalFile(const CharacterType* spec, int pathBegin, int specLength, URLSegments& parsed) -{ - parsed.host.reset(); - parsePathInternal(spec, URLComponent::fromRange(pathBegin, specLength), - &parsed.path, &parsed.query, &parsed.fragment); -} - -// Backend for the external functions that operates on either char type. -// We are handed the character after the "file:" at the beginning of the spec. -// Usually this is a slash, but needn't be; we allow paths like "file:c:\foo". -template<typename CharacterType> -void doParseFileURL(const CharacterType* spec, int specLength, URLSegments& parsed) -{ - ASSERT(specLength >= 0); - - // Get the parts we never use for file URLs out of the way. - parsed.username.reset(); - parsed.password.reset(); - parsed.port.reset(); - - // Many of the code paths don't set these, so it's convenient to just clear - // them. We'll write them in those cases we need them. - parsed.query.reset(); - parsed.fragment.reset(); - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - // Find the scheme. - int numSlashes; - int afterScheme; - int afterSlashes; -#if OS(WINDOWS) - // See how many slashes there are. We want to handle cases like UNC but also - // "/c:/foo". This is when there is no scheme, so we can allow pages to do - // links like "c:/foo/bar" or "//foo/bar". This is also called by the - // relative URL resolver when it determines there is an absolute URL, which - // may give us input like "/c:/foo". - numSlashes = countConsecutiveSlashes(spec, begin, specLength); - afterSlashes = begin + numSlashes; - if (doesBeginWindowsDriveSpec(spec, afterSlashes, specLength)) { - // Windows path, don't try to extract the scheme (for example, "c:\foo"). - parsed.scheme.reset(); - afterScheme = afterSlashes; - } else if (doesBeginUNCPath(spec, begin, specLength, false)) { - // Windows UNC path: don't try to extract the scheme, but keep the slashes. - parsed.scheme.reset(); - afterScheme = begin; - } else -#endif - { - if (ExtractScheme(&spec[begin], specLength - begin, &parsed.scheme)) { - // Offset the results since we gave ExtractScheme a substring. - parsed.scheme.moveBy(begin); - afterScheme = parsed.scheme.end() + 1; - } else { - // No scheme found, remember that. - parsed.scheme.reset(); - afterScheme = begin; - } - } - - // Handle empty specs ones that contain only whitespace or control chars, - // or that are just the scheme (for example "file:"). - if (afterScheme == specLength) { - parsed.host.reset(); - parsed.path.reset(); - return; - } - - numSlashes = countConsecutiveSlashes(spec, afterScheme, specLength); - - afterSlashes = afterScheme + numSlashes; -#if OS(WINDOWS) - // Check whether the input is a drive again. We checked above for windows - // drive specs, but that's only at the very beginning to see if we have a - // scheme at all. This test will be duplicated in that case, but will - // additionally handle all cases with a real scheme such as "file:///C:/". - if (!doesBeginWindowsDriveSpec(spec, afterSlashes, specLength) && numSlashes != 3) { - // Anything not beginning with a drive spec ("c:\") on Windows is treated - // as UNC, with the exception of three slashes which always means a file. - // Even IE7 treats file:///foo/bar as "/foo/bar", which then fails. - doParseUNC(spec, afterSlashes, specLength, parsed); - return; - } -#else - // file: URL with exactly 2 slashes is considered to have a host component. - if (numSlashes == 2) { - doParseUNC(spec, afterSlashes, specLength, parsed); - return; - } -#endif // OS(WINDOWS) - - // Easy and common case, the full path immediately follows the scheme - // (modulo slashes), as in "file://c:/foo". Just treat everything from - // there to the end as the path. Empty hosts have 0 length instead of -1. - // We include the last slash as part of the path if there is one. - doParseLocalFile(spec, - numSlashes > 0 ? afterScheme + numSlashes - 1 : afterScheme, - specLength, parsed); -} - -} // namespace - -void ParseFileURL(const char* url, int urlLength, URLSegments* parsed) -{ - doParseFileURL(url, urlLength, *parsed); -} - -void ParseFileURL(const UChar* url, int urlLength, URLSegments* parsed) -{ - doParseFileURL(url, urlLength, *parsed); -} - -} // namespace URLParser - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLParseInternal.h b/Source/WTF/wtf/url/src/URLParseInternal.h deleted file mode 100644 index de27aedd0..000000000 --- a/Source/WTF/wtf/url/src/URLParseInternal.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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. - */ - -// Contains common inline helper functions used by the URL parsing routines. - -#ifndef URLParseInternal_h -#define URLParseInternal_h - -#include "URLParse.h" -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLParser { - -// We treat slashes and backslashes the same for IE compatability. -inline bool isURLSlash(UChar ch) -{ - return ch == '/' || ch == '\\'; -} - -// Returns true if we should trim this character from the URL because it is a -// space or a control character. -inline bool shouldTrimFromURL(UChar ch) -{ - return ch <= ' '; -} - -// Given an already-initialized begin index and length, this shrinks the range -// to eliminate "should-be-trimmed" characters. Note that the length does *not* -// indicate the length of untrimmed data from |*begin|, but rather the position -// in the input string (so the string starts at character |*begin| in the spec, -// and goes until |*len|). -template<typename CharacterType> -inline void trimURL(const CharacterType* spec, int& begin, int& length) -{ - // Strip leading whitespace and control characters. - while (begin < length && 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 (length > begin && shouldTrimFromURL(spec[length - 1])) - --length; -} - -// Counts the number of consecutive slashes starting at the given offset -// in the given string of the given length. -template<typename CharacterType> -inline int countConsecutiveSlashes(const CharacterType *str, int begin_offset, int strLength) -{ - int count = 0; - while (begin_offset + count < strLength && isURLSlash(str[begin_offset + count])) - ++count; - return count; -} - -// Internal functions in URLParser.cc that parse the path, that is, everything -// following the authority section. The input is the range of everything -// following the authority section, and the output is the identified ranges. -// -// This is designed for the file URL parser or other consumers who may do -// special stuff at the beginning, but want regular path parsing, it just -// maps to the internal parsing function for paths. -void parsePathInternal(const char* spec, - const URLComponent& path, - URLComponent* filepath, - URLComponent* query, - URLComponent* fragment); -void parsePathInternal(const UChar* spec, - const URLComponent& path, - URLComponent* filepath, - URLComponent* query, - URLComponent* fragment); - - -// Given a spec and a pointer to the character after the colon following the -// scheme, this parses it and fills in the structure, Every item in the parsed -// structure is filled EXCEPT for the scheme, which is untouched. -void parseAfterScheme(const char* spec, int specLength, int afterScheme, URLSegments& parsed); -void parseAfterScheme(const UChar* spec, int specLength, int afterScheme, URLSegments& parsed); - -} // namespace URLParser - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLParseInternal_h diff --git a/Source/WTF/wtf/url/src/URLSegments.cpp b/Source/WTF/wtf/url/src/URLSegments.cpp deleted file mode 100644 index 14c95be39..000000000 --- a/Source/WTF/wtf/url/src/URLSegments.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Based on nsURLParsers.cc from Mozilla - * ------------------------------------- - * Copyright (C) 1998 Netscape Communications Corporation. - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * 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, DelimiterExcluded); -} - -int URLSegments::charactersBefore(ComponentType type, DelimiterInclusion 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 == DelimiterIncluded)) - 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 == DelimiterIncluded)) - 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 == DelimiterExcluded) - 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; -} - -void URLSegments::moveFromComponentBy(ComponentType type, int offset) -{ - switch (type) { - // Fall through. - case Scheme: - scheme.moveBy(offset); - case Username: - username.moveBy(offset); - case Password: - password.moveBy(offset); - case Host: - host.moveBy(offset); - case Port: - port.moveBy(offset); - case Path: - path.moveBy(offset); - case Query: - query.moveBy(offset); - case Fragment: - fragment.moveBy(offset); - } -} - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLSegments.h b/Source/WTF/wtf/url/src/URLSegments.h deleted file mode 100644 index 971eec390..000000000 --- a/Source/WTF/wtf/url/src/URLSegments.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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" -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> - -#if USE(WTFURL) - -namespace WTF { - -class URLSegments; - -// 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, - }; - enum DelimiterInclusion { - DelimiterExcluded, - DelimiterIncluded - }; - - URLSegments() { } - - URLSegments(const URLSegments& otherSegment) - { - *this = otherSegment; - } - - URLSegments& operator=(const URLSegments& otherSegment) - { - scheme = otherSegment.scheme; - username = otherSegment.username; - password = otherSegment.password; - host = otherSegment.host; - port = otherSegment.port; - path = otherSegment.path; - query = otherSegment.query; - fragment = otherSegment.fragment; - if (otherSegment.m_innerURLSegments) - m_innerURLSegments = adoptPtr(new URLSegments(*otherSegment.m_innerURLSegments)); - return *this; - } - - // 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, DelimiterInclusion) const; - - // Shift all the components from 'firstComponent' to the last component by 'offset'. - void moveFromComponentBy(ComponentType firstComponent, int offset); - - // 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; - - // FIXME: this is a damn ugly API and is basically untested. - const URLSegments* innerURLSegments() const { return m_innerURLSegments.get(); } - void setInnerURLSegments(const URLSegments& urlSegments) { m_innerURLSegments = adoptPtr(new URLSegments(urlSegments)); } - void clearInnerURLSegments() { return m_innerURLSegments.clear(); } - -private: - // The Filesystem API describe a URL format with an internal URL. E.g.: filesystem:http://www.apple.com/ - // The inner URL segment contains the parsed inner URL of a filesystem: URL. - OwnPtr<URLSegments> m_innerURLSegments; -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLSegments_h diff --git a/Source/WTF/wtf/url/src/URLUtil.cpp b/Source/WTF/wtf/url/src/URLUtil.cpp deleted file mode 100644 index 4a429a1fb..000000000 --- a/Source/WTF/wtf/url/src/URLUtil.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 "URLUtil.h" - -#include "RawURLBuffer.h" -#include "URLCanonInternal.h" -#include "URLFile.h" -#include "URLUtilInternal.h" -#include <wtf/ASCIICType.h> - -#if USE(WTFURL) - -namespace WTF { - -namespace URLUtilities { - -const char kFileScheme[] = "file"; -const char kFileSystemScheme[] = "filesystem"; -const char kMailtoScheme[] = "mailto"; - -namespace { - -template<typename Iter> -static bool lowerCaseEqualsASCII(Iter aBegin, Iter aEnd, const char* b) -{ - for (Iter it = aBegin; it != aEnd; ++it, ++b) { - if (!*b || toASCIILower(*it) != *b) - return false; - } - return !(*b); -} - -const int kNumStandardURLSchemes = 8; -const char* kStandardURLSchemes[kNumStandardURLSchemes] = { - "http", - "https", - kFileScheme, // Yes, file urls can have a hostname! - "ftp", - "gopher", - "ws", // WebSocket. - "wss", // WebSocket secure. - kFileSystemScheme -}; - -// Given a string and a range inside the string, compares it to the given -// lower-case |compareTo| buffer. -template<typename CharacterType> -inline bool doCompareSchemeComponent(const CharacterType* spec, const URLComponent& component, const char* compareTo) -{ - if (!component.isNonEmpty()) - return !compareTo[0]; // When component is empty, match empty scheme. - return lowerCaseEqualsASCII(&spec[component.begin()], &spec[component.end()], compareTo); -} - -// Returns true if the given scheme identified by |scheme| within |spec| is one -// of the registered "standard" schemes. -template<typename CharacterType> -bool doIsStandard(const CharacterType* spec, const URLComponent& scheme) -{ - if (!scheme.isNonEmpty()) - return false; // Empty or invalid schemes are non-standard. - - for (size_t i = 0; i < kNumStandardURLSchemes; ++i) { - if (lowerCaseEqualsASCII(&spec[scheme.begin()], &spec[scheme.end()], kStandardURLSchemes[i])) - return true; - } - return false; -} - -template<typename CharacterType> -bool doFindAndCompareScheme(const CharacterType* str, int strLength, const char* compare, URLComponent* foundScheme) -{ - // Before extracting scheme, canonicalize the URL to remove any whitespace. - // This matches the canonicalization done in doCanonicalize function. - RawURLBuffer<CharacterType> whitespaceBuffer; - int specLength; - const CharacterType* spec = URLCanonicalizer::removeURLWhitespace(str, strLength, whitespaceBuffer, specLength); - - URLComponent ourScheme; - if (!URLParser::ExtractScheme(spec, specLength, &ourScheme)) { - // No scheme. - if (foundScheme) - *foundScheme = URLComponent(); - return false; - } - if (foundScheme) - *foundScheme = ourScheme; - return doCompareSchemeComponent(spec, ourScheme, compare); -} - -template<typename CharacterType> -bool doCanonicalize(const CharacterType* inSpec, int inSpecLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments& ouputParsed) -{ - // Remove any whitespace from the middle of the relative URL, possibly - // copying to the new buffer. - RawURLBuffer<CharacterType> whitespaceBuffer; - int specLength; - const CharacterType* spec = URLCanonicalizer::removeURLWhitespace(inSpec, inSpecLength, whitespaceBuffer, specLength); - - URLSegments parsedInput; -#if OS(WINDOWS) - // For Windows, we allow things that look like absolute Windows paths to be - // fixed up magically to file URLs. This is done for IE compatability. For - // example, this will change "c:/foo" into a file URL rather than treating - // it as a URL with the protocol "c". It also works for UNC ("\\foo\bar.txt"). - // There is similar logic in URLCanonicalizer_relative.cc for - // - // For Max & Unix, we don't do this (the equivalent would be "/foo/bar" which - // has no meaning as an absolute path name. This is because browsers on Mac - // & Unix don't generally do this, so there is no compatibility reason for - // doing so. - if (URLParser::doesBeginUNCPath(spec, 0, specLength, false) - || URLParser::doesBeginWindowsDriveSpec(spec, 0, specLength)) { - URLParser::ParseFileURL(spec, specLength, &parsedInput); - return URLCanonicalizer::CanonicalizeFileURL(spec, specLength, parsedInput, - charsetConverter, - output, *ouputParsed); - } -#endif - - URLComponent scheme; - if (!URLParser::ExtractScheme(spec, specLength, &scheme)) - return false; - - // This is the parsed version of the input URL, we have to canonicalize it - // before storing it in our object. - bool success; - if (doCompareSchemeComponent(spec, scheme, kFileScheme)) { - // File URLs are special. - URLParser::ParseFileURL(spec, specLength, &parsedInput); - success = URLCanonicalizer::CanonicalizeFileURL(spec, specLength, parsedInput, - charsetConverter, output, - &ouputParsed); - } else if (doCompareSchemeComponent(spec, scheme, kFileSystemScheme)) { - // Filesystem URLs are special. - URLParser::ParseFileSystemURL(spec, specLength, &parsedInput); - success = URLCanonicalizer::canonicalizeFileSystemURL(spec, parsedInput, - charsetConverter, - output, ouputParsed); - - } else if (doIsStandard(spec, scheme)) { - // All "normal" URLs. - URLParser::ParseStandardURL(spec, specLength, &parsedInput); - success = URLCanonicalizer::CanonicalizeStandardURL(spec, specLength, parsedInput, - charsetConverter, - output, &ouputParsed); - - } else if (doCompareSchemeComponent(spec, scheme, kMailtoScheme)) { - // Mailto are treated like a standard url with only a scheme, path, query - URLParser::ParseMailtoURL(spec, specLength, &parsedInput); - success = URLCanonicalizer::canonicalizeMailtoURL(spec, parsedInput, output, ouputParsed); - - } else { - // "Weird" URLs like data: and javascript: - URLParser::ParsePathURL(spec, specLength, &parsedInput); - success = URLCanonicalizer::canonicalizePathURL(spec, parsedInput, output, ouputParsed); - } - return success; -} - -template<typename CharacterType> -bool doResolveRelative(const char* baseSpec, const URLSegments& baseParsed, - const CharacterType* inRelative, int inRelativeLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments* ouputParsed) -{ - // Remove any whitespace from the middle of the relative URL, possibly - // copying to the new buffer. - RawURLBuffer<CharacterType> whitespaceBuffer; - int relativeLength; - const CharacterType* relative = URLCanonicalizer::removeURLWhitespace(inRelative, inRelativeLength, whitespaceBuffer, relativeLength); - - // See if our base URL should be treated as "standard". - bool standardBaseScheme = baseParsed.scheme.isNonEmpty() && doIsStandard(baseSpec, baseParsed.scheme); - - bool isRelative; - URLComponent relativeComponent; - if (!URLCanonicalizer::isRelativeURL(baseSpec, baseParsed, - relative, relativeLength, - standardBaseScheme, - isRelative, relativeComponent)) - return false; // Error resolving. - - if (isRelative) { - // Relative, resolve and canonicalize. - bool fileBaseScheme = baseParsed.scheme.isNonEmpty() && doCompareSchemeComponent(baseSpec, baseParsed.scheme, kFileScheme); - return URLCanonicalizer::resolveRelativeURL(baseSpec, baseParsed, - fileBaseScheme, relative, - relativeComponent, charsetConverter, - output, ouputParsed); - } - - // Not relative, canonicalize the input. - return doCanonicalize(relative, relativeLength, charsetConverter, output, *ouputParsed); -} - -template<typename CharacterType> -bool doReplaceComponents(const char* spec, - int specLength, - const URLSegments& parsed, - const URLCanonicalizer::Replacements<CharacterType>& replacements, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments& outputParsed) -{ - // If the scheme is overridden, just do a simple string substitution and - // reparse the whole thing. There are lots of edge cases that we really don't - // want to deal with. Like what happens if I replace "http://e:8080/foo" - // with a file. Does it become "file:///E:/8080/foo" where the port number - // becomes part of the path? Parsing that string as a file URL says "yes" - // but almost no sane rule for dealing with the components individually would - // come up with that. - // - // Why allow these crazy cases at all? Programatically, there is almost no - // case for replacing the scheme. The most common case for hitting this is - // in JS when building up a URL using the location object. In this case, the - // JS code expects the string substitution behavior: - // http://www.w3.org/TR/2008/WD-html5-20080610/structured.html#common3 - if (replacements.IsSchemeOverridden()) { - // Canonicalize the new scheme so it is 8-bit and can be concatenated with - // the existing spec. - RawURLBuffer<char, 128> scheme_replaced; - URLComponent schemeReplacedParsed; - URLCanonicalizer::canonicalizeScheme(replacements.sources().scheme, - replacements.components().scheme, - scheme_replaced, schemeReplacedParsed); - - // We can assume that the input is canonicalized, which means it always has - // a colon after the scheme (or where the scheme would be). - int specAfterColon = parsed.scheme.isValid() ? parsed.scheme.end() + 1 - : 1; - if (specLength - specAfterColon > 0) { - scheme_replaced.append(&spec[specAfterColon], - specLength - specAfterColon); - } - - // We now need to completely re-parse the resulting string since its meaning - // may have changed with the different scheme. - RawURLBuffer<char, 128> recanonicalized; - URLSegments recanonicalizedParsed; - doCanonicalize(scheme_replaced.data(), scheme_replaced.length(), - charsetConverter, - recanonicalized, recanonicalizedParsed); - - // Recurse using the version with the scheme already replaced. This will now - // use the replacement rules for the new scheme. - // - // Warning: this code assumes that ReplaceComponents will re-check all - // components for validity. This is because we can't fail if DoCanonicalize - // failed above since theoretically the thing making it fail could be - // getting replaced here. If ReplaceComponents didn't re-check everything, - // we wouldn't know if something *not* getting replaced is a problem. - // If the scheme-specific replacers are made more intelligent so they don't - // re-check everything, we should instead recanonicalize the whole thing - // after this call to check validity (this assumes replacing the scheme is - // much much less common than other types of replacements, like clearing the - // ref). - URLCanonicalizer::Replacements<CharacterType> replacementsNoScheme = replacements; - replacementsNoScheme.SetScheme(0, URLComponent()); - return doReplaceComponents(recanonicalized.data(), recanonicalized.length(), - recanonicalizedParsed, replacementsNoScheme, - charsetConverter, output, outputParsed); - } - - // If we get here, then we know the scheme doesn't need to be replaced, so can - // just key off the scheme in the spec to know how to do the replacements. - if (doCompareSchemeComponent(spec, parsed.scheme, kFileScheme)) { - return URLCanonicalizer::ReplaceFileURL(spec, parsed, replacements, - charsetConverter, output, &outputParsed); - } - if (doCompareSchemeComponent(spec, parsed.scheme, kFileSystemScheme)) { - return URLCanonicalizer::ReplaceFileSystemURL(spec, parsed, replacements, - charsetConverter, output, - &outputParsed); - } - if (doIsStandard(spec, parsed.scheme)) { - return URLCanonicalizer::ReplaceStandardURL(spec, parsed, replacements, - charsetConverter, output, &outputParsed); - } - if (doCompareSchemeComponent(spec, parsed.scheme, kMailtoScheme)) - return URLCanonicalizer::replaceMailtoURL(spec, parsed, replacements, output, outputParsed); - - // Default is a path URL. - return URLCanonicalizer::ReplacePathURL(spec, parsed, replacements, output, &outputParsed); -} - -} // namespace - -bool isStandard(const LChar* spec, const URLComponent& scheme) -{ - return doIsStandard(spec, scheme); -} - -bool isStandard(const UChar* spec, const URLComponent& scheme) -{ - return doIsStandard(spec, scheme); -} - -bool FindAndCompareScheme(const char* str, int strLength, const char* compare, URLComponent* foundScheme) -{ - return doFindAndCompareScheme(str, strLength, compare, foundScheme); -} - -bool FindAndCompareScheme(const UChar* str, int strLength, const char* compare, URLComponent* foundScheme) -{ - return doFindAndCompareScheme(str, strLength, compare, foundScheme); -} - -bool canonicalize(const char* spec, int specLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments& ouputParsed) -{ - return doCanonicalize(spec, specLength, charsetConverter, output, ouputParsed); -} - -bool canonicalize(const UChar* spec, int specLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments& ouputParsed) -{ - return doCanonicalize(spec, specLength, charsetConverter, output, ouputParsed); -} - -bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, - const char* relative, int relativeLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments* ouputParsed) -{ - return doResolveRelative(baseSpec, baseParsed, - relative, relativeLength, - charsetConverter, output, ouputParsed); -} - -bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, - const UChar* relative, int relativeLength, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, URLSegments* ouputParsed) -{ - return doResolveRelative(baseSpec, baseParsed, - relative, relativeLength, - charsetConverter, output, ouputParsed); -} - -bool ReplaceComponents(const char* spec, - int specLength, - const URLSegments& parsed, - const URLCanonicalizer::Replacements<char>& replacements, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doReplaceComponents(spec, specLength, parsed, replacements, - charsetConverter, output, *outputParsed); -} - -bool ReplaceComponents(const char* spec, - int specLength, - const URLSegments& parsed, - const URLCanonicalizer::Replacements<UChar>& replacements, - URLQueryCharsetConverter* charsetConverter, - URLBuffer<char>& output, - URLSegments* outputParsed) -{ - return doReplaceComponents(spec, specLength, parsed, replacements, - charsetConverter, output, *outputParsed); -} - -void DecodeURLEscapeSequences(const char* input, int length, URLBuffer<UChar>& output) -{ - RawURLBuffer<char> unescapedChars; - for (int i = 0; i < length; ++i) { - if (input[i] == '%') { - unsigned char ch; - if (URLCanonicalizer::DecodeEscaped(input, &i, length, &ch)) - unescapedChars.append(ch); - else { - // Invalid escape sequence, copy the percent literal. - unescapedChars.append('%'); - } - } else { - // Regular non-escaped 8-bit character. - unescapedChars.append(input[i]); - } - } - - // Convert that 8-bit to UTF-16. It's not clear IE does this at all to - // JavaScript URLs, but Firefox and Safari do. - for (int i = 0; i < unescapedChars.length(); i++) { - unsigned char uch = static_cast<unsigned char>(unescapedChars.at(i)); - if (uch < 0x80) { - // Non-UTF-8, just append directly - output.append(uch); - } else { - // next_ch will point to the last character of the decoded - // character. - int nextCharacter = i; - unsigned codePoint; - if (URLCanonicalizer::readUTFChar(unescapedChars.data(), &nextCharacter, - unescapedChars.length(), &codePoint)) { - // Valid UTF-8 character, convert to UTF-16. - URLCanonicalizer::AppendUTF16Value(codePoint, output); - i = nextCharacter; - } else { - // If there are any sequences that are not valid UTF-8, we keep - // invalid code points and promote to UTF-16. We copy all characters - // from the current position to the end of the identified sequence. - while (i < nextCharacter) { - output.append(static_cast<unsigned char>(unescapedChars.at(i))); - i++; - } - output.append(static_cast<unsigned char>(unescapedChars.at(i))); - } - } - } -} - -void EncodeURIComponent(const char* input, int length, URLBuffer<char>& output) -{ - for (int i = 0; i < length; ++i) { - unsigned char c = static_cast<unsigned char>(input[i]); - if (URLCharacterTypes::isComponentChar(c)) - output.append(c); - else - URLCanonicalizer::appendURLEscapedCharacter(c, output); - } -} - -bool CompareSchemeComponent(const char* spec, const URLComponent& component, const char* compareTo) -{ - return doCompareSchemeComponent(spec, component, compareTo); -} - -bool CompareSchemeComponent(const UChar* spec, const URLComponent& component, const char* compareTo) -{ - return doCompareSchemeComponent(spec, component, compareTo); -} - -} // namespace URLUtilities - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLUtil.h b/Source/WTF/wtf/url/src/URLUtil.h deleted file mode 100644 index e85a33461..000000000 --- a/Source/WTF/wtf/url/src/URLUtil.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2007 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 URLUtil_h -#define URLUtil_h - -#include "URLBuffer.h" -#include "URLCanon.h" -#include "URLParse.h" -#include <wtf/unicode/Unicode.h> - -#if USE(WTFURL) - -namespace WTF { - -class URLQueryCharsetConverter; - -namespace URLUtilities { - -// Locates the scheme in the given string and places it into |foundScheme|, -// which may be 0 to indicate the caller does not care about the range. -// -// Returns whether the given |compare| scheme matches the scheme found in the -// input (if any). The |compare| scheme must be a valid canonical scheme or -// the result of the comparison is undefined. -bool FindAndCompareScheme(const char* str, int strLength, const char* compare, URLComponent* foundScheme); -bool FindAndCompareScheme(const UChar* str, int strLength, const char* compare, URLComponent* foundScheme); - -// Returns true if the given string represents a standard URL. This means that -// either the scheme is in the list of known standard schemes. -bool isStandard(const LChar* spec, const URLComponent& scheme); -bool isStandard(const UChar* spec, const URLComponent& scheme); -inline bool isStandard(const char* spec, const URLComponent& scheme) { return isStandard(reinterpret_cast<const LChar*>(spec), scheme); } - -// URL library wrappers ------------------------------------------------------- - -// Parses the given spec according to the extracted scheme type. Normal users -// should use the URL object, although this may be useful if performance is -// critical and you don't want to do the heap allocation for the std::string. -// -// As with the URLCanonicalizer::Canonicalize* functions, the charset converter can -// be 0 to use UTF-8 (it will be faster in this case). -// -// Returns true if a valid URL was produced, false if not. On failure, the -// output and parsed structures will still be filled and will be consistent, -// but they will not represent a loadable URL. -bool canonicalize(const char* spec, int specLength, URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments& ouputParsed); -bool canonicalize(const UChar* spec, int specLength, URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments& ouputParsed); - -// Resolves a potentially relative URL relative to the given parsed base URL. -// The base MUST be valid. The resulting canonical URL and parsed information -// will be placed in to the given out variables. -// -// The relative need not be relative. If we discover that it's absolute, this -// will produce a canonical version of that URL. See Canonicalize() for more -// about the charsetConverter. -// -// Returns true if the output is valid, false if the input could not produce -// a valid URL. -bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, - const char* relative, int relativeLength, - URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments* ouputParsed); -bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, - const UChar* relative, int relativeLength, - URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments* ouputParsed); - -// Replaces components in the given VALID input url. The new canonical URL info -// is written to output and outputParsed. -// -// Returns true if the resulting URL is valid. -bool ReplaceComponents(const char* spec, int specLength, const URLSegments& parsed, - const URLCanonicalizer::Replacements<char>&, - URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments* outputParsed); -bool ReplaceComponents(const char* spec, int specLength, const URLSegments& parsed, - const URLCanonicalizer::Replacements<UChar>&, - URLQueryCharsetConverter*, - URLBuffer<char>&, URLSegments* outputParsed); - -// Unescapes the given string using URL escaping rules. -void DecodeURLEscapeSequences(const char* input, int length, URLBuffer<UChar>&); - -// Escapes the given string as defined by the JS method encodeURIComponent. -// See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent -void EncodeURIComponent(const char* input, int length, URLBuffer<char>&); - - -} // namespace URLUtilities - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLUtil_h diff --git a/Source/WTF/wtf/url/src/URLUtilInternal.h b/Source/WTF/wtf/url/src/URLUtilInternal.h deleted file mode 100644 index 0840aec86..000000000 --- a/Source/WTF/wtf/url/src/URLUtilInternal.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011 Google Inc. All rights reserved. - * Copyright 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: - * - * * 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 URLUtilInternal_h -#define URLUtilInternal_h - -#include "URLParse.h" - -#if USE(WTFURL) - -namespace WTF { - -namespace URLUtilities { - -extern const char kFileScheme[]; -extern const char kFileSystemScheme[]; -extern const char kMailtoScheme[]; - -// Given a string and a range inside the string, compares it to the given -// lower-case |compareTo| buffer. -bool CompareSchemeComponent(const char* spec, const URLComponent&, const char* compareTo); -bool CompareSchemeComponent(const UChar* spec, const URLComponent&, const char* compareTo); - -} // namespace URLUtilities - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLUtilInternal_h diff --git a/Source/WTF/wtf/win/MainThreadWin.cpp b/Source/WTF/wtf/win/MainThreadWin.cpp index ee3a27377..75f1deec9 100644 --- a/Source/WTF/wtf/win/MainThreadWin.cpp +++ b/Source/WTF/wtf/win/MainThreadWin.cpp @@ -32,9 +32,7 @@ #include "Assertions.h" #include "Threading.h" -#if !OS(WINCE) #include <windows.h> -#endif namespace WTF { @@ -57,26 +55,18 @@ void initializeMainThreadPlatform() return; HWND hWndParent = 0; -#if OS(WINCE) - WNDCLASS wcex; - memset(&wcex, 0, sizeof(WNDCLASS)); -#else - WNDCLASSEX wcex; - memset(&wcex, 0, sizeof(WNDCLASSEX)); - wcex.cbSize = sizeof(WNDCLASSEX); -#endif + WNDCLASSW wcex; + memset(&wcex, 0, sizeof(WNDCLASSW)); wcex.lpfnWndProc = ThreadingWindowWndProc; wcex.lpszClassName = kThreadingWindowClassName; -#if OS(WINCE) - RegisterClass(&wcex); -#else - RegisterClassEx(&wcex); + RegisterClassW(&wcex); +#if !OS(WINCE) hWndParent = HWND_MESSAGE; #endif - threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0, + threadingWindowHandle = CreateWindowW(kThreadingWindowClassName, 0, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndParent, 0, 0, 0); - threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired"); + threadingFiredMessage = RegisterWindowMessageW(L"com.apple.WebKit.MainThreadFired"); initializeCurrentThreadInternal("Main Thread"); } diff --git a/Source/WTF/wtf/win/OwnPtrWin.cpp b/Source/WTF/wtf/win/OwnPtrWin.cpp index 67a32ff77..d625e2063 100644 --- a/Source/WTF/wtf/win/OwnPtrWin.cpp +++ b/Source/WTF/wtf/win/OwnPtrWin.cpp @@ -27,6 +27,8 @@ #include "config.h" #include "OwnPtr.h" +#if OS(WINDOWS) + #include <windows.h> namespace WTF { @@ -73,4 +75,6 @@ void deleteOwnedPtr(HRGN ptr) DeleteObject(ptr); } -} +} // namespace WTF + +#endif // OS(WINDOWS) diff --git a/Source/WTF/wtf/wince/FastMallocWinCE.h b/Source/WTF/wtf/wince/FastMallocWinCE.h deleted file mode 100644 index 3601249cf..000000000 --- a/Source/WTF/wtf/wince/FastMallocWinCE.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_FastMallocWinCE_h -#define WTF_FastMallocWinCE_h - -#include <new.h> - -#ifdef __cplusplus -#include <new> -#include <wtf/wince/MemoryManager.h> -extern "C" { -#endif - -void* fastMalloc(size_t n); -void* fastCalloc(size_t n_elements, size_t element_size); -void fastFree(void* p); -void* fastRealloc(void* p, size_t n); -void* fastZeroedMalloc(size_t n); -// These functions return 0 if an allocation fails. -void* tryFastMalloc(size_t n); -void* tryFastZeroedMalloc(size_t n); -void* tryFastCalloc(size_t n_elements, size_t element_size); -void* tryFastRealloc(void* p, size_t n); -char* fastStrDup(const char*); - -#ifndef NDEBUG -void fastMallocForbid(); -void fastMallocAllow(); -#endif - -#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC - -#define malloc(n) fastMalloc(n) -#define calloc(n_elements, element_size) fastCalloc(n_elements, element_size) -#define realloc(p, n) fastRealloc(p, n) -#define free(p) fastFree(p) -#define strdup(p) fastStrDup(p) - -#else - -#define strdup(p) _strdup(p) - -#endif - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC -static inline void* __cdecl operator new(size_t s) { return fastMalloc(s); } -static inline void __cdecl operator delete(void* p) { fastFree(p); } -static inline void* __cdecl operator new[](size_t s) { return fastMalloc(s); } -static inline void __cdecl operator delete[](void* p) { fastFree(p); } -static inline void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); } -static inline void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } -static inline void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); } -static inline void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } -#endif - -namespace WTF { - // This defines a type which holds an unsigned integer and is the same - // size as the minimally aligned memory allocation. - typedef unsigned long long AllocAlignmentInteger; - - namespace Internal { - enum AllocType { // Start with an unusual number instead of zero, because zero is common. - AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. - AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. - AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. - AllocTypeFastNew, // Encompasses fastNew. - AllocTypeFastNewArray, // Encompasses fastNewArray. - AllocTypeNew, // Encompasses global operator new. - AllocTypeNewArray // Encompasses global operator new[]. - }; - } - - -#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) - - // Malloc validation is a scheme whereby a tag is attached to an - // allocation which identifies how it was originally allocated. - // This allows us to verify that the freeing operation matches the - // allocation operation. If memory is allocated with operator new[] - // but freed with free or delete, this system would detect that. - // In the implementation here, the tag is an integer prepended to - // the allocation memory which is assigned one of the AllocType - // enumeration values. An alternative implementation of this - // scheme could store the tag somewhere else or ignore it. - // Users of FastMalloc don't need to know or care how this tagging - // is implemented. - - namespace Internal { - - // Return the AllocType tag associated with the allocated block p. - inline AllocType fastMallocMatchValidationType(const void* p) - { - const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1; - return static_cast<AllocType>(*type); - } - - // Return the address of the AllocType tag associated with the allocated block p. - inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p) - { - return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger)); - } - - // Set the AllocType tag to be associaged with the allocated block p. - inline void setFastMallocMatchValidationType(void* p, AllocType allocType) - { - AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1; - *type = static_cast<AllocAlignmentInteger>(allocType); - } - - // Handle a detected alloc/free mismatch. By default this calls CRASH(). - void fastMallocMatchFailed(void* p); - - } // namespace Internal - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) - { - if (!p) - return; - - Internal::setFastMallocMatchValidationType(p, allocType); - } - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType) - { - if (!p) - return; - - if (Internal::fastMallocMatchValidationType(p) != allocType) - Internal::fastMallocMatchFailed(p); - Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. - } - -#else - - inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) - { - } - - inline void fastMallocMatchValidateFree(void*, Internal::AllocType) - { - } - -#endif - -} // namespace WTF - -#endif - -#endif // WTF_FastMallocWinCE_h diff --git a/Source/WTF/wtf/wince/MemoryManager.cpp b/Source/WTF/wtf/wince/MemoryManager.cpp deleted file mode 100644 index 81d4f805b..000000000 --- a/Source/WTF/wtf/wince/MemoryManager.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2008-2009 Torch Mobile Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "MemoryManager.h" - -#undef malloc -#undef calloc -#undef realloc -#undef free -#undef strdup -#undef _strdup -#undef VirtualAlloc -#undef VirtualFree - -#include <malloc.h> -#include <windows.h> - -namespace WTF { - -MemoryManager* memoryManager() -{ - static MemoryManager mm; - return &mm; -} - -MemoryManager::MemoryManager() -: m_allocationCanFail(false) -{ -} - -MemoryManager::~MemoryManager() -{ -} - -HBITMAP MemoryManager::createCompatibleBitmap(HDC hdc, int width, int height) -{ - return ::CreateCompatibleBitmap(hdc, width, height); -} - -HBITMAP MemoryManager::createDIBSection(const BITMAPINFO* pbmi, void** ppvBits) -{ - return ::CreateDIBSection(0, pbmi, DIB_RGB_COLORS, ppvBits, 0, 0); -} - -void* MemoryManager::m_malloc(size_t size) -{ - return malloc(size); -} - -void* MemoryManager::m_calloc(size_t num, size_t size) -{ - return calloc(num, size); -} - -void* MemoryManager::m_realloc(void* p, size_t size) -{ - return realloc(p, size); -} - -void MemoryManager::m_free(void* p) -{ - return free(p); -} - -bool MemoryManager::resizeMemory(void*, size_t) -{ - return false; -} - -void* MemoryManager::allocate64kBlock() -{ - return VirtualAlloc(0, 65536, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -} - -void MemoryManager::free64kBlock(void* p) -{ - VirtualFree(p, 65536, MEM_RELEASE); -} - -bool MemoryManager::onIdle(DWORD& timeLimitMs) -{ - return false; -} - -LPVOID MemoryManager::virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect) -{ - return ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); -} - -BOOL MemoryManager::virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType) -{ - return ::VirtualFree(lpAddress, dwSize, dwFreeType); -} - - -#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC - -void *fastMalloc(size_t n) { return malloc(n); } -void *fastCalloc(size_t n_elements, size_t element_size) { return calloc(n_elements, element_size); } -void fastFree(void* p) { return free(p); } -void *fastRealloc(void* p, size_t n) { return realloc(p, n); } - -#else - -void *fastMalloc(size_t n) { return MemoryManager::m_malloc(n); } -void *fastCalloc(size_t n_elements, size_t element_size) { return MemoryManager::m_calloc(n_elements, element_size); } -void fastFree(void* p) { return MemoryManager::m_free(p); } -void *fastRealloc(void* p, size_t n) { return MemoryManager::m_realloc(p, n); } - -#endif - -#ifndef NDEBUG -void fastMallocForbid() {} -void fastMallocAllow() {} -#endif - -void* fastZeroedMalloc(size_t n) -{ - void* p = fastMalloc(n); - if (p) - memset(p, 0, n); - return p; -} - -TryMallocReturnValue tryFastMalloc(size_t n) -{ - MemoryAllocationCanFail canFail; - return fastMalloc(n); -} - -TryMallocReturnValue tryFastZeroedMalloc(size_t n) -{ - MemoryAllocationCanFail canFail; - return fastZeroedMalloc(n); -} - -TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size) -{ - MemoryAllocationCanFail canFail; - return fastCalloc(n_elements, element_size); -} - -TryMallocReturnValue tryFastRealloc(void* p, size_t n) -{ - MemoryAllocationCanFail canFail; - return fastRealloc(p, n); -} - -char* fastStrDup(const char* str) -{ - return _strdup(str); -} - -}
\ No newline at end of file diff --git a/Source/WTF/wtf/wince/MemoryManager.h b/Source/WTF/wtf/wince/MemoryManager.h deleted file mode 100644 index f405612df..000000000 --- a/Source/WTF/wtf/wince/MemoryManager.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2008-2009 Torch Mobile Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#pragma once - -#include <winbase.h> - -typedef struct HBITMAP__* HBITMAP; -typedef struct HDC__* HDC; -typedef void *HANDLE; -typedef struct tagBITMAPINFO BITMAPINFO; - -namespace WTF { - - class MemoryManager { - public: - MemoryManager(); - ~MemoryManager(); - - bool allocationCanFail() const { return m_allocationCanFail; } - void setAllocationCanFail(bool c) { m_allocationCanFail = c; } - - static HBITMAP createCompatibleBitmap(HDC hdc, int width, int height); - static HBITMAP createDIBSection(const BITMAPINFO* pbmi, void** ppvBits); - static void* m_malloc(size_t size); - static void* m_calloc(size_t num, size_t size); - static void* m_realloc(void* p, size_t size); - static void m_free(void*); - static bool resizeMemory(void* p, size_t newSize); - static void* allocate64kBlock(); - static void free64kBlock(void*); - static bool onIdle(DWORD& timeLimitMs); - static LPVOID virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); - static BOOL virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType); - - private: - friend MemoryManager* memoryManager(); - - bool m_allocationCanFail; - }; - - MemoryManager* memoryManager(); - - class MemoryAllocationCanFail { - public: - MemoryAllocationCanFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(true); } - ~MemoryAllocationCanFail() { memoryManager()->setAllocationCanFail(m_old); } - private: - bool m_old; - }; - - class MemoryAllocationCannotFail { - public: - MemoryAllocationCannotFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(false); } - ~MemoryAllocationCannotFail() { memoryManager()->setAllocationCanFail(m_old); } - private: - bool m_old; - }; -} - -using WTF::MemoryManager; -using WTF::memoryManager; -using WTF::MemoryAllocationCanFail; -using WTF::MemoryAllocationCannotFail; diff --git a/Source/WTF/wtf/wx/StringWx.cpp b/Source/WTF/wtf/wx/StringWx.cpp deleted file mode 100644 index d5f6c578a..000000000 --- a/Source/WTF/wtf/wx/StringWx.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 Vaclav Slavik, Kevin Ollivier <kevino@theolliviers.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -// The wx headers must come first in this case, because the wtf/text headers -// import windows.h, and we need to allow the wx headers to set its configuration -// first. -#include <wx/defs.h> -#include <wx/string.h> - -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -String::String(const wxString& wxstr) -{ -#if !wxUSE_UNICODE - #error "This code only works in Unicode build of wxWidgets" -#endif - -#if SIZEOF_WCHAR_T == 2 - - const UChar* str = wxstr.wc_str(); - const size_t len = wxstr.length(); - -#else // SIZEOF_WCHAR_T == 4 - - // NB: we can't simply use wxstr.mb_str(wxMBConvUTF16()) here because - // the number of characters in UTF-16 encoding of the string may differ - // from the number of UTF-32 values and we can't get the length from - // returned buffer: - -#if defined(wxUSE_UNICODE_UTF8) && wxUSE_UNICODE_UTF8 - // in wx3's UTF8 mode, wc_str() returns a buffer, not raw pointer - wxWCharBuffer wideString(wxstr.wc_str()); -#else - const wxChar *wideString = wxstr.wc_str(); -#endif - size_t wideLength = wxstr.length(); - - wxMBConvUTF16 conv; - - const size_t utf16bufLen = conv.FromWChar(0, 0, wideString, wideLength); - wxCharBuffer utf16buf(utf16bufLen); - - const UChar* str = (const UChar*)utf16buf.data(); - size_t len = conv.FromWChar(utf16buf.data(), utf16bufLen, wideString, wideLength) / 2; - -#endif // SIZEOF_WCHAR_T == 2 - - m_impl = StringImpl::create(str, len); - -} - -String::operator wxString() const -{ - return wxString(utf8().data(), wxConvUTF8); -} - -} // namespace WTF |
