tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebCore / platform / text / cf / StringImplCF.cpp
1 /*
2  * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include <wtf/text/StringImpl.h>
23
24 #if USE(CF)
25
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <wtf/MainThread.h>
28 #include <wtf/PassRefPtr.h>
29 #include <wtf/Threading.h>
30
31 #if PLATFORM(MAC)
32 #include <objc/objc-auto.h>
33 #endif
34
35 namespace WTF {
36
37 namespace StringWrapperCFAllocator {
38
39     static StringImpl* currentString;
40
41     static const void* retain(const void* info)
42     {
43         return info;
44     }
45
46     NO_RETURN_DUE_TO_ASSERT
47     static void release(const void*)
48     {
49         ASSERT_NOT_REACHED();
50     }
51
52     static CFStringRef copyDescription(const void*)
53     {
54         return CFSTR("WTF::String-based allocator");
55     }
56
57     static void* allocate(CFIndex size, CFOptionFlags, void*)
58     {
59         StringImpl* underlyingString = 0;
60         if (isMainThread()) {
61             underlyingString = currentString;
62             if (underlyingString) {
63                 currentString = 0;
64                 underlyingString->ref(); // Balanced by call to deref in deallocate below.
65             }
66         }
67         StringImpl** header = static_cast<StringImpl**>(fastMalloc(sizeof(StringImpl*) + size));
68         *header = underlyingString;
69         return header + 1;
70     }
71
72     static void* reallocate(void* pointer, CFIndex newSize, CFOptionFlags, void*)
73     {
74         size_t newAllocationSize = sizeof(StringImpl*) + newSize;
75         StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
76         ASSERT(!*header);
77         header = static_cast<StringImpl**>(fastRealloc(header, newAllocationSize));
78         return header + 1;
79     }
80
81     static void deallocateOnMainThread(void* headerPointer)
82     {
83         StringImpl** header = static_cast<StringImpl**>(headerPointer);
84         StringImpl* underlyingString = *header;
85         ASSERT(underlyingString);
86         underlyingString->deref(); // Balanced by call to ref in allocate above.
87         fastFree(header);
88     }
89
90     static void deallocate(void* pointer, void*)
91     {
92         StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
93         StringImpl* underlyingString = *header;
94         if (!underlyingString)
95             fastFree(header);
96         else {
97             if (!isMainThread())
98                 callOnMainThread(deallocateOnMainThread, header);
99             else {
100                 underlyingString->deref(); // Balanced by call to ref in allocate above.
101                 fastFree(header);
102             }
103         }
104     }
105
106     static CFIndex preferredSize(CFIndex size, CFOptionFlags, void*)
107     {
108         // FIXME: If FastMalloc provided a "good size" callback, we'd want to use it here.
109         // Note that this optimization would help performance for strings created with the
110         // allocator that are mutable, and those typically are only created by callers who
111         // make a new string using the old string's allocator, such as some of the call
112         // sites in CFURL.
113         return size;
114     }
115
116     static CFAllocatorRef create()
117     {
118 #if PLATFORM(MAC)
119         // Since garbage collection isn't compatible with custom allocators, don't use this at all when garbage collection is active.
120         if (objc_collectingEnabled())
121             return 0;
122 #endif
123         CFAllocatorContext context = { 0, 0, retain, release, copyDescription, allocate, reallocate, deallocate, preferredSize };
124         return CFAllocatorCreate(0, &context);
125     }
126
127     static CFAllocatorRef allocator()
128     {
129         static CFAllocatorRef allocator = create();
130         return allocator;
131     }
132
133 }
134
135 CFStringRef StringImpl::createCFString()
136 {
137     CFAllocatorRef allocator = (m_length && isMainThread()) ? StringWrapperCFAllocator::allocator() : 0;
138     if (!allocator)
139         return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(characters()), m_length);
140
141     // Put pointer to the StringImpl in a global so the allocator can store it with the CFString.
142     ASSERT(!StringWrapperCFAllocator::currentString);
143     StringWrapperCFAllocator::currentString = this;
144
145     CFStringRef string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(characters()), m_length, kCFAllocatorNull);
146
147     // The allocator cleared the global when it read it, but also clear it here just in case.
148     ASSERT(!StringWrapperCFAllocator::currentString);
149     StringWrapperCFAllocator::currentString = 0;
150
151     return string;
152 }
153
154 // On StringImpl creation we could check if the allocator is the StringWrapperCFAllocator.
155 // If it is, then we could find the original StringImpl and just return that. But to
156 // do that we'd have to compute the offset from CFStringRef to the allocated block;
157 // the CFStringRef is *not* at the start of an allocated block. Testing shows 1000x
158 // more calls to createCFString than calls to the create functions with the appropriate
159 // allocator, so it's probably not urgent optimize that case.
160
161 }
162
163 #endif // USE(CF)