Remove all uses of PassRefPtr in WTF
[WebKit-https.git] / Source / WTF / wtf / text / cf / StringImplCF.cpp
1 /*
2  * Copyright (C) 2006, 2009, 2012 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/RetainPtr.h>
29 #include <wtf/Threading.h>
30
31 namespace WTF {
32
33 namespace StringWrapperCFAllocator {
34
35     static StringImpl* currentString;
36
37     static const void* retain(const void* info)
38     {
39         return info;
40     }
41
42     NO_RETURN_DUE_TO_ASSERT
43     static void release(const void*)
44     {
45         ASSERT_NOT_REACHED();
46     }
47
48     static CFStringRef copyDescription(const void*)
49     {
50         return CFSTR("WTF::String-based allocator");
51     }
52
53     static void* allocate(CFIndex size, CFOptionFlags, void*)
54     {
55         StringImpl* underlyingString = 0;
56         if (isMainThread()) {
57             underlyingString = currentString;
58             if (underlyingString) {
59                 currentString = 0;
60                 underlyingString->ref(); // Balanced by call to deref in deallocate below.
61             }
62         }
63         StringImpl** header = static_cast<StringImpl**>(fastMalloc(sizeof(StringImpl*) + size));
64         *header = underlyingString;
65         return header + 1;
66     }
67
68     static void* reallocate(void* pointer, CFIndex newSize, CFOptionFlags, void*)
69     {
70         size_t newAllocationSize = sizeof(StringImpl*) + newSize;
71         StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
72         ASSERT(!*header);
73         header = static_cast<StringImpl**>(fastRealloc(header, newAllocationSize));
74         return header + 1;
75     }
76
77     static void deallocate(void* pointer, void*)
78     {
79         StringImpl** header = static_cast<StringImpl**>(pointer) - 1;
80         StringImpl* underlyingString = *header;
81         if (!underlyingString)
82             fastFree(header);
83         else {
84             if (isMainThread()) {
85                 underlyingString->deref(); // Balanced by call to ref in allocate above.
86                 fastFree(header);
87                 return;
88             }
89
90             callOnMainThread([header] {
91                 StringImpl* underlyingString = *header;
92                 ASSERT(underlyingString);
93                 underlyingString->deref(); // Balanced by call to ref in allocate above.
94                 fastFree(header);
95             });
96         }
97     }
98
99     static CFIndex preferredSize(CFIndex size, CFOptionFlags, void*)
100     {
101         // FIXME: If FastMalloc provided a "good size" callback, we'd want to use it here.
102         // Note that this optimization would help performance for strings created with the
103         // allocator that are mutable, and those typically are only created by callers who
104         // make a new string using the old string's allocator, such as some of the call
105         // sites in CFURL.
106         return size;
107     }
108
109     static CFAllocatorRef create()
110     {
111         CFAllocatorContext context = { 0, 0, retain, release, copyDescription, allocate, reallocate, deallocate, preferredSize };
112         return CFAllocatorCreate(0, &context);
113     }
114
115     static CFAllocatorRef allocator()
116     {
117         static CFAllocatorRef allocator = create();
118         return allocator;
119     }
120
121 }
122
123 RetainPtr<CFStringRef> StringImpl::createCFString()
124 {
125     if (!m_length || !isMainThread()) {
126         if (is8Bit())
127             return adoptCF(CFStringCreateWithBytes(0, reinterpret_cast<const UInt8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false));
128         return adoptCF(CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(characters16()), m_length));
129     }
130     CFAllocatorRef allocator = StringWrapperCFAllocator::allocator();
131
132     // Put pointer to the StringImpl in a global so the allocator can store it with the CFString.
133     ASSERT(!StringWrapperCFAllocator::currentString);
134     StringWrapperCFAllocator::currentString = this;
135
136     CFStringRef string;
137     if (is8Bit())
138         string = CFStringCreateWithBytesNoCopy(allocator, reinterpret_cast<const UInt8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false, kCFAllocatorNull);
139     else
140         string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<const UniChar*>(characters16()), m_length, kCFAllocatorNull);
141     // CoreFoundation might not have to allocate anything, we clear currentString in case we did not execute allocate().
142     StringWrapperCFAllocator::currentString = 0;
143
144     return adoptCF(string);
145 }
146
147 // On StringImpl creation we could check if the allocator is the StringWrapperCFAllocator.
148 // If it is, then we could find the original StringImpl and just return that. But to
149 // do that we'd have to compute the offset from CFStringRef to the allocated block;
150 // the CFStringRef is *not* at the start of an allocated block. Testing shows 1000x
151 // more calls to createCFString than calls to the create functions with the appropriate
152 // allocator, so it's probably not urgent optimize that case.
153
154 }
155
156 #endif // USE(CF)