1 | /* |
2 | * Copyright (C) 2013-2017 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 | #pragma once |
27 | |
28 | #include <functional> |
29 | #include <wtf/Deque.h> |
30 | #include <wtf/Forward.h> |
31 | |
32 | namespace WebCore { |
33 | |
34 | class SharedBuffer; |
35 | |
36 | class KeyedDecoder { |
37 | WTF_MAKE_FAST_ALLOCATED; |
38 | public: |
39 | WEBCORE_EXPORT static std::unique_ptr<KeyedDecoder> decoder(const uint8_t* data, size_t); |
40 | |
41 | virtual ~KeyedDecoder() = default; |
42 | |
43 | virtual bool decodeBytes(const String& key, const uint8_t*&, size_t&) = 0; |
44 | virtual bool decodeBool(const String& key, bool&) = 0; |
45 | virtual bool decodeUInt32(const String& key, uint32_t&) = 0; |
46 | virtual bool decodeUInt64(const String& key, uint64_t&) = 0; |
47 | virtual bool decodeInt32(const String& key, int32_t&) = 0; |
48 | virtual bool decodeInt64(const String& key, int64_t&) = 0; |
49 | virtual bool decodeFloat(const String& key, float&) = 0; |
50 | virtual bool decodeDouble(const String& key, double&) = 0; |
51 | virtual bool decodeString(const String& key, String&) = 0; |
52 | |
53 | template<typename T> |
54 | bool decodeBytes(const String& key, Vector<T>& vector) |
55 | { |
56 | static_assert(sizeof(T) == 1, "" ); |
57 | |
58 | size_t size; |
59 | const uint8_t* bytes; |
60 | if (!decodeBytes(key, bytes, size)) |
61 | return false; |
62 | |
63 | vector.resize(size); |
64 | std::copy(bytes, bytes + size, vector.data()); |
65 | return true; |
66 | } |
67 | |
68 | template<typename T, typename F> |
69 | bool decodeEnum(const String& key, T& value, F&& isValidEnumFunction) |
70 | { |
71 | static_assert(std::is_enum<T>::value, "T must be an enum type" ); |
72 | |
73 | int64_t intValue; |
74 | if (!decodeInt64(key, intValue)) |
75 | return false; |
76 | |
77 | if (!isValidEnumFunction(static_cast<T>(intValue))) |
78 | return false; |
79 | |
80 | value = static_cast<T>(intValue); |
81 | return true; |
82 | } |
83 | |
84 | template<typename T, typename F> |
85 | bool decodeObject(const String& key, T& object, F&& function) |
86 | { |
87 | if (!beginObject(key)) |
88 | return false; |
89 | bool result = function(*this, object); |
90 | endObject(); |
91 | return result; |
92 | } |
93 | |
94 | template<typename T, typename F> |
95 | bool decodeConditionalObject(const String& key, T& object, F&& function) |
96 | { |
97 | // FIXME: beginObject can return false for two reasons: either the |
98 | // key doesn't exist or the key refers to something that isn't an object. |
99 | // Because of this, decodeConditionalObject won't distinguish between a |
100 | // missing object or a value that isn't an object. |
101 | if (!beginObject(key)) |
102 | return true; |
103 | |
104 | bool result = function(*this, object); |
105 | endObject(); |
106 | return result; |
107 | } |
108 | |
109 | template<typename ContainerType, typename F> |
110 | bool decodeObjects(const String& key, ContainerType& objects, F&& function) |
111 | { |
112 | if (!beginArray(key)) |
113 | return false; |
114 | |
115 | bool result = true; |
116 | while (beginArrayElement()) { |
117 | typename ContainerType::ValueType element; |
118 | if (!function(*this, element)) { |
119 | result = false; |
120 | endArrayElement(); |
121 | break; |
122 | } |
123 | objects.append(WTFMove(element)); |
124 | endArrayElement(); |
125 | } |
126 | |
127 | endArray(); |
128 | return result; |
129 | } |
130 | |
131 | protected: |
132 | KeyedDecoder() |
133 | { |
134 | } |
135 | |
136 | private: |
137 | virtual bool beginObject(const String& key) = 0; |
138 | virtual void endObject() = 0; |
139 | |
140 | virtual bool beginArray(const String& key) = 0; |
141 | virtual bool beginArrayElement() = 0; |
142 | virtual void endArrayElement() = 0; |
143 | virtual void endArray() = 0; |
144 | }; |
145 | |
146 | class KeyedEncoder { |
147 | WTF_MAKE_FAST_ALLOCATED; |
148 | public: |
149 | WEBCORE_EXPORT static std::unique_ptr<KeyedEncoder> encoder(); |
150 | |
151 | virtual ~KeyedEncoder() = default; |
152 | |
153 | virtual void encodeBytes(const String& key, const uint8_t*, size_t) = 0; |
154 | virtual void encodeBool(const String& key, bool) = 0; |
155 | virtual void encodeUInt32(const String& key, uint32_t) = 0; |
156 | virtual void encodeUInt64(const String& key, uint64_t) = 0; |
157 | virtual void encodeInt32(const String& key, int32_t) = 0; |
158 | virtual void encodeInt64(const String& key, int64_t) = 0; |
159 | virtual void encodeFloat(const String& key, float) = 0; |
160 | virtual void encodeDouble(const String& key, double) = 0; |
161 | virtual void encodeString(const String& key, const String&) = 0; |
162 | |
163 | virtual RefPtr<SharedBuffer> finishEncoding() = 0; |
164 | |
165 | template<typename T> |
166 | void encodeEnum(const String& key, T value) |
167 | { |
168 | static_assert(std::is_enum<T>::value, "T must be an enum type" ); |
169 | |
170 | encodeInt64(key, static_cast<int64_t>(value)); |
171 | } |
172 | |
173 | template<typename T, typename F> |
174 | void encodeObject(const String& key, const T& object, F&& function) |
175 | { |
176 | beginObject(key); |
177 | function(*this, object); |
178 | endObject(); |
179 | } |
180 | |
181 | template<typename T, typename F> |
182 | void encodeConditionalObject(const String& key, const T* object, F&& function) |
183 | { |
184 | if (!object) |
185 | return; |
186 | |
187 | encodeObject(key, *object, std::forward<F>(function)); |
188 | } |
189 | |
190 | template<typename T, typename F> |
191 | void encodeObjects(const String& key, T begin, T end, F&& function) |
192 | { |
193 | beginArray(key); |
194 | for (T it = begin; it != end; ++it) { |
195 | beginArrayElement(); |
196 | function(*this, *it); |
197 | endArrayElement(); |
198 | } |
199 | endArray(); |
200 | } |
201 | |
202 | protected: |
203 | KeyedEncoder() |
204 | { |
205 | } |
206 | |
207 | private: |
208 | virtual void beginObject(const String& key) = 0; |
209 | virtual void endObject() = 0; |
210 | |
211 | virtual void beginArray(const String& key) = 0; |
212 | virtual void beginArrayElement() = 0; |
213 | virtual void endArrayElement() = 0; |
214 | virtual void endArray() = 0; |
215 | }; |
216 | |
217 | } // namespace WebCore |
218 | |