[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / cf / KeyedDecoderCF.cpp
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "KeyedDecoderCF.h"
28
29 #include <wtf/cf/TypeCastsCF.h>
30 #include <wtf/text/WTFString.h>
31
32 namespace WebCore {
33
34 std::unique_ptr<KeyedDecoder> KeyedDecoder::decoder(const uint8_t* data, size_t size)
35 {
36     return makeUnique<KeyedDecoderCF>(data, size);
37 }
38
39 KeyedDecoderCF::KeyedDecoderCF(const uint8_t* data, size_t size)
40 {
41     auto cfData = adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, data, size, kCFAllocatorNull));
42     auto cfPropertyList = adoptCF(CFPropertyListCreateWithData(kCFAllocatorDefault, cfData.get(), kCFPropertyListImmutable, nullptr, nullptr));
43
44     if (dynamic_cf_cast<CFDictionaryRef>(cfPropertyList.get()))
45         m_rootDictionary = adoptCF(static_cast<CFDictionaryRef>(cfPropertyList.leakRef()));
46     else
47         m_rootDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
48     m_dictionaryStack.append(m_rootDictionary.get());
49 }
50
51 KeyedDecoderCF::~KeyedDecoderCF()
52 {
53     ASSERT(m_dictionaryStack.size() == 1);
54     ASSERT(m_dictionaryStack.last() == m_rootDictionary);
55     ASSERT(m_arrayStack.isEmpty());
56     ASSERT(m_arrayIndexStack.isEmpty());
57 }
58
59 bool KeyedDecoderCF::decodeBytes(const String& key, const uint8_t*& bytes, size_t& size)
60 {
61     auto data = dynamic_cf_cast<CFDataRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
62     if (!data)
63         return false;
64
65     bytes = CFDataGetBytePtr(data);
66     size = CFDataGetLength(data);
67     return true;
68 }
69
70 bool KeyedDecoderCF::decodeBool(const String& key, bool& result)
71 {
72     auto boolean = dynamic_cf_cast<CFBooleanRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
73     if (!boolean)
74         return false;
75
76     result = CFBooleanGetValue(boolean);
77     return true;
78 }
79
80 bool KeyedDecoderCF::decodeUInt32(const String& key, uint32_t& result)
81 {
82     return decodeInt32(key, reinterpret_cast<int32_t&>(result));
83 }
84     
85 bool KeyedDecoderCF::decodeUInt64(const String& key, uint64_t& result)
86 {
87     return decodeInt64(key, reinterpret_cast<int64_t&>(result));
88 }
89
90 bool KeyedDecoderCF::decodeInt32(const String& key, int32_t& result)
91 {
92     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
93     if (!number)
94         return false;
95
96     return CFNumberGetValue(number, kCFNumberSInt32Type, &result);
97 }
98
99 bool KeyedDecoderCF::decodeInt64(const String& key, int64_t& result)
100 {
101     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
102     if (!number)
103         return false;
104
105     return CFNumberGetValue(number, kCFNumberSInt64Type, &result);
106 }
107
108 bool KeyedDecoderCF::decodeFloat(const String& key, float& result)
109 {
110     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
111     if (!number)
112         return false;
113
114     return CFNumberGetValue(number, kCFNumberFloatType, &result);
115 }
116
117 bool KeyedDecoderCF::decodeDouble(const String& key, double& result)
118 {
119     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
120     if (!number)
121         return false;
122
123     return CFNumberGetValue(number, kCFNumberDoubleType, &result);
124 }
125
126 bool KeyedDecoderCF::decodeString(const String& key, String& result)
127 {
128     auto string = dynamic_cf_cast<CFStringRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
129     if (!string)
130         return false;
131
132     result = string;
133     return true;
134 }
135
136 bool KeyedDecoderCF::beginObject(const String& key)
137 {
138     auto dictionary = dynamic_cf_cast<CFDictionaryRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
139     if (!dictionary)
140         return false;
141
142     m_dictionaryStack.append(dictionary);
143     return true;
144 }
145
146 void KeyedDecoderCF::endObject()
147 {
148     m_dictionaryStack.removeLast();
149 }
150
151 bool KeyedDecoderCF::beginArray(const String& key)
152 {
153     auto array = dynamic_cf_cast<CFArrayRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
154     if (!array)
155         return false;
156
157     for (CFIndex i = 0; i < CFArrayGetCount(array); ++i) {
158         CFTypeRef object = CFArrayGetValueAtIndex(array, i);
159         if (CFGetTypeID(object) != CFDictionaryGetTypeID())
160             return false;
161     }
162
163     m_arrayStack.append(array);
164     m_arrayIndexStack.append(0);
165     return true;
166 }
167
168 bool KeyedDecoderCF::beginArrayElement()
169 {
170     if (m_arrayIndexStack.last() >= CFArrayGetCount(m_arrayStack.last()))
171         return false;
172
173     auto dictionary = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(m_arrayStack.last(), m_arrayIndexStack.last()++));
174     m_dictionaryStack.append(dictionary);
175     return true;
176 }
177
178 void KeyedDecoderCF::endArrayElement()
179 {
180     m_dictionaryStack.removeLast();
181 }
182
183 void KeyedDecoderCF::endArray()
184 {
185     m_arrayStack.removeLast();
186     m_arrayIndexStack.removeLast();
187 }
188
189 } // namespace WebCore