Replace WTF::move with WTFMove
[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 std::make_unique<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
43     if (auto rootDictionary = adoptCF(dynamic_cf_cast<CFDictionaryRef>(CFPropertyListCreateWithData(kCFAllocatorDefault, cfData.get(), kCFPropertyListImmutable, nullptr, nullptr))))
44         m_rootDictionary = WTFMove(rootDictionary);
45     else
46         m_rootDictionary = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, nullptr, nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
47     m_dictionaryStack.append(m_rootDictionary.get());
48 }
49
50 KeyedDecoderCF::~KeyedDecoderCF()
51 {
52     ASSERT(m_dictionaryStack.size() == 1);
53     ASSERT(m_dictionaryStack.last() == m_rootDictionary);
54     ASSERT(m_arrayStack.isEmpty());
55     ASSERT(m_arrayIndexStack.isEmpty());
56 }
57
58 bool KeyedDecoderCF::decodeBytes(const String& key, const uint8_t*& bytes, size_t& size)
59 {
60     auto data = dynamic_cf_cast<CFDataRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
61     if (!data)
62         return false;
63
64     bytes = CFDataGetBytePtr(data);
65     size = CFDataGetLength(data);
66     return true;
67 }
68
69 bool KeyedDecoderCF::decodeBool(const String& key, bool& result)
70 {
71     auto boolean = dynamic_cf_cast<CFBooleanRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
72     if (!boolean)
73         return false;
74
75     result = CFBooleanGetValue(boolean);
76     return true;
77 }
78
79 bool KeyedDecoderCF::decodeUInt32(const String& key, uint32_t& result)
80 {
81     return decodeInt32(key, reinterpret_cast<int32_t&>(result));
82 }
83
84 bool KeyedDecoderCF::decodeInt32(const String& key, int32_t& result)
85 {
86     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
87     if (!number)
88         return false;
89
90     return CFNumberGetValue(number, kCFNumberSInt32Type, &result);
91 }
92
93 bool KeyedDecoderCF::decodeInt64(const String& key, int64_t& result)
94 {
95     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
96     if (!number)
97         return false;
98
99     return CFNumberGetValue(number, kCFNumberSInt64Type, &result);
100 }
101
102 bool KeyedDecoderCF::decodeFloat(const String& key, float& result)
103 {
104     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
105     if (!number)
106         return false;
107
108     return CFNumberGetValue(number, kCFNumberFloatType, &result);
109 }
110
111 bool KeyedDecoderCF::decodeDouble(const String& key, double& result)
112 {
113     auto number = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
114     if (!number)
115         return false;
116
117     return CFNumberGetValue(number, kCFNumberDoubleType, &result);
118 }
119
120 bool KeyedDecoderCF::decodeString(const String& key, String& result)
121 {
122     auto string = dynamic_cf_cast<CFStringRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
123     if (!string)
124         return false;
125
126     result = string;
127     return true;
128 }
129
130 bool KeyedDecoderCF::beginObject(const String& key)
131 {
132     auto dictionary = dynamic_cf_cast<CFDictionaryRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
133     if (!dictionary)
134         return false;
135
136     m_dictionaryStack.append(dictionary);
137     return true;
138 }
139
140 void KeyedDecoderCF::endObject()
141 {
142     m_dictionaryStack.removeLast();
143 }
144
145 bool KeyedDecoderCF::beginArray(const String& key)
146 {
147     auto array = dynamic_cf_cast<CFArrayRef>(CFDictionaryGetValue(m_dictionaryStack.last(), key.createCFString().get()));
148     if (!array)
149         return false;
150
151     for (CFIndex i = 0; i < CFArrayGetCount(array); ++i) {
152         CFTypeRef object = CFArrayGetValueAtIndex(array, i);
153         if (CFGetTypeID(object) != CFDictionaryGetTypeID())
154             return false;
155     }
156
157     m_arrayStack.append(array);
158     m_arrayIndexStack.append(0);
159     return true;
160 }
161
162 bool KeyedDecoderCF::beginArrayElement()
163 {
164     if (m_arrayIndexStack.last() >= CFArrayGetCount(m_arrayStack.last()))
165         return false;
166
167     auto dictionary = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(m_arrayStack.last(), m_arrayIndexStack.last()++));
168     m_dictionaryStack.append(dictionary);
169     return true;
170 }
171
172 void KeyedDecoderCF::endArrayElement()
173 {
174     m_dictionaryStack.removeLast();
175 }
176
177 void KeyedDecoderCF::endArray()
178 {
179     m_arrayStack.removeLast();
180     m_arrayIndexStack.removeLast();
181 }
182
183 } // namespace WebCore