| Flutter macOS Embedder |

FlutterStandardCodecHelper.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodecHelper.h"
6 #include <stdint.h>
7
8 #include <vector>
9
10 #include "flutter/fml/logging.h"
11
12 // The google-runtime-int lint suggests uint64_t in place of unsigned long,
13 // however these functions are frequently used with NSUInteger, which is
14 // defined as an unsigned long.
15 //
16 // NOLINTBEGIN(google-runtime-int)
17
18 void FlutterStandardCodecHelperReadAlignment(unsigned long* location,
19 uint8_t alignment) {
20 uint8_t mod = *location % alignment;
21 if (mod) {
22 *location += (alignment - mod);
23 }
24 }
25
26 static uint8_t PeekByte(unsigned long location, CFDataRef data) {
27 uint8_t result;
28 CFRange range = CFRangeMake(location, 1);
29 CFDataGetBytes(data, range, &result);
30 return result;
31 }
32
33 void FlutterStandardCodecHelperReadBytes(unsigned long* location,
34 unsigned long length,
35 void* destination,
36 CFDataRef data) {
37 CFRange range = CFRangeMake(*location, length);
38 CFDataGetBytes(data, range, static_cast<UInt8*>(destination));
39 *location += length;
40 }
41
42 uint8_t FlutterStandardCodecHelperReadByte(unsigned long* location,
43 CFDataRef data) {
44 uint8_t value;
45 FlutterStandardCodecHelperReadBytes(location, 1, &value, data);
46 return value;
47 }
48
49 uint32_t FlutterStandardCodecHelperReadSize(unsigned long* location,
50 CFDataRef data) {
51 uint8_t byte = FlutterStandardCodecHelperReadByte(location, data);
52 if (byte < 254) {
53 return (uint32_t)byte;
54 } else if (byte == 254) {
55 UInt16 value;
56 FlutterStandardCodecHelperReadBytes(location, 2, &value, data);
57 return value;
58 } else {
59 UInt32 value;
60 FlutterStandardCodecHelperReadBytes(location, 4, &value, data);
61 return value;
62 }
63 }
64
65 static CFDataRef ReadDataNoCopy(unsigned long* location,
66 unsigned long length,
67 CFDataRef data) {
68 CFDataRef result = CFDataCreateWithBytesNoCopy(
69 kCFAllocatorDefault, CFDataGetBytePtr(data) + *location, length,
70 kCFAllocatorNull);
71 *location += length;
72 return static_cast<CFDataRef>(CFAutorelease(result));
73 }
74
75 CFStringRef FlutterStandardCodecHelperReadUTF8(unsigned long* location,
76 CFDataRef data) {
77 uint32_t size = FlutterStandardCodecHelperReadSize(location, data);
78 CFDataRef bytes = ReadDataNoCopy(location, size, data);
79 CFStringRef result = CFStringCreateFromExternalRepresentation(
80 kCFAllocatorDefault, bytes, kCFStringEncodingUTF8);
81 return static_cast<CFStringRef>(CFAutorelease(result));
82 }
83
84 // Peeks ahead to see if we are reading a standard type. If so, recurse
85 // directly to FlutterStandardCodecHelperReadValueOfType, otherwise recurse to
86 // objc.
87 static inline CFTypeRef FastReadValue(
88 unsigned long* location,
89 CFDataRef data,
90 CFTypeRef (*ReadValue)(CFTypeRef),
91 CFTypeRef (*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef),
92 CFTypeRef user_data) {
93 uint8_t type = PeekByte(*location, data);
94 if (FlutterStandardFieldIsStandardType(type)) {
95 *location += 1;
96 return FlutterStandardCodecHelperReadValueOfType(
97 location, data, type, ReadValue, ReadTypedDataOfType, user_data);
98 } else {
99 return ReadValue(user_data);
100 }
101 }
102
103 CFTypeRef FlutterStandardCodecHelperReadValueOfType(
104 unsigned long* location,
105 CFDataRef data,
106 uint8_t type,
107 CFTypeRef (*ReadValue)(CFTypeRef),
108 CFTypeRef (*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef),
109 CFTypeRef user_data) {
110 FlutterStandardField field = (FlutterStandardField)type;
111 switch (field) {
112 case FlutterStandardFieldNil:
113 return nil;
114 case FlutterStandardFieldTrue:
115 return kCFBooleanTrue;
116 case FlutterStandardFieldFalse:
117 return kCFBooleanFalse;
118 case FlutterStandardFieldInt32: {
119 int32_t value;
120 FlutterStandardCodecHelperReadBytes(location, 4, &value, data);
121 return CFAutorelease(
122 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value));
123 }
124 case FlutterStandardFieldInt64: {
125 int64_t value;
126 FlutterStandardCodecHelperReadBytes(location, 8, &value, data);
127 return CFAutorelease(
128 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
129 }
130 case FlutterStandardFieldFloat64: {
131 Float64 value;
132 FlutterStandardCodecHelperReadAlignment(location, 8);
133 FlutterStandardCodecHelperReadBytes(location, 8, &value, data);
134 return CFAutorelease(
135 CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
136 }
137 case FlutterStandardFieldIntHex:
138 case FlutterStandardFieldString:
139 return FlutterStandardCodecHelperReadUTF8(location, data);
140 case FlutterStandardFieldUInt8Data:
141 case FlutterStandardFieldInt32Data:
142 case FlutterStandardFieldInt64Data:
143 case FlutterStandardFieldFloat32Data:
144 case FlutterStandardFieldFloat64Data:
145 return ReadTypedDataOfType(field, user_data);
146 case FlutterStandardFieldList: {
147 UInt32 length = FlutterStandardCodecHelperReadSize(location, data);
148 CFMutableArrayRef array = CFArrayCreateMutable(
149 kCFAllocatorDefault, length, &kCFTypeArrayCallBacks);
150 for (UInt32 i = 0; i < length; i++) {
151 CFTypeRef value = FastReadValue(location, data, ReadValue,
152 ReadTypedDataOfType, user_data);
153 CFArrayAppendValue(array, (value == nil ? kCFNull : value));
154 }
155 return CFAutorelease(array);
156 }
157 case FlutterStandardFieldMap: {
158 UInt32 size = FlutterStandardCodecHelperReadSize(location, data);
159 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
160 kCFAllocatorDefault, size, &kCFTypeDictionaryKeyCallBacks,
161 &kCFTypeDictionaryValueCallBacks);
162 for (UInt32 i = 0; i < size; i++) {
163 CFTypeRef key = FastReadValue(location, data, ReadValue,
164 ReadTypedDataOfType, user_data);
165 CFTypeRef val = FastReadValue(location, data, ReadValue,
166 ReadTypedDataOfType, user_data);
167 CFDictionaryAddValue(dict, (key == nil ? kCFNull : key),
168 (val == nil ? kCFNull : val));
169 }
170 return CFAutorelease(dict);
171 }
172 default:
173 // Malformed message.
174 FML_DCHECK(false);
175 }
176 }
177
178 void FlutterStandardCodecHelperWriteByte(CFMutableDataRef data, uint8_t value) {
179 CFDataAppendBytes(data, &value, 1);
180 }
181
182 void FlutterStandardCodecHelperWriteBytes(CFMutableDataRef data,
183 const void* bytes,
184 unsigned long length) {
185 CFDataAppendBytes(data, static_cast<const UInt8*>(bytes), length);
186 }
187
188 void FlutterStandardCodecHelperWriteSize(CFMutableDataRef data, uint32_t size) {
189 if (size < 254) {
190 FlutterStandardCodecHelperWriteByte(data, size);
191 } else if (size <= 0xffff) {
192 FlutterStandardCodecHelperWriteByte(data, 254);
193 UInt16 value = (UInt16)size;
194 FlutterStandardCodecHelperWriteBytes(data, &value, 2);
195 } else {
196 FlutterStandardCodecHelperWriteByte(data, 255);
197 FlutterStandardCodecHelperWriteBytes(data, &size, 4);
198 }
199 }
200
201 void FlutterStandardCodecHelperWriteAlignment(CFMutableDataRef data,
202 uint8_t alignment) {
203 uint8_t mod = CFDataGetLength(data) % alignment;
204 if (mod) {
205 for (int i = 0; i < (alignment - mod); i++) {
206 FlutterStandardCodecHelperWriteByte(data, 0);
207 }
208 }
209 }
210
211 void FlutterStandardCodecHelperWriteUTF8(CFMutableDataRef data,
212 CFStringRef value) {
213 const char* utf8 = CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
214 if (utf8) {
215 size_t length = strlen(utf8);
216 FlutterStandardCodecHelperWriteSize(data, length);
217 FlutterStandardCodecHelperWriteBytes(data, utf8, length);
218 } else {
219 CFIndex length = CFStringGetLength(value);
220 CFIndex used_length = 0;
221 // UTF16 length times 3 will fit all UTF8.
222 CFIndex buffer_length = length * 3;
223 std::vector<UInt8> buffer;
224 buffer.reserve(buffer_length);
225 CFStringGetBytes(value, CFRangeMake(0, length), kCFStringEncodingUTF8, 0,
226 false, buffer.data(), buffer_length, &used_length);
227 FlutterStandardCodecHelperWriteSize(data, used_length);
228 FlutterStandardCodecHelperWriteBytes(data, buffer.data(), used_length);
229 }
230 }
231
232 void FlutterStandardCodecHelperWriteData(CFMutableDataRef data,
233 CFDataRef value) {
234 const UInt8* bytes = CFDataGetBytePtr(value);
235 CFIndex length = CFDataGetLength(value);
236 FlutterStandardCodecHelperWriteBytes(data, bytes, length);
237 }
238
239 bool FlutterStandardCodecHelperWriteNumber(CFMutableDataRef data,
240 CFNumberRef number) {
241 bool success = false;
242 if (CFGetTypeID(number) == CFBooleanGetTypeID()) {
243 bool b = CFBooleanGetValue((CFBooleanRef)number);
244 FlutterStandardCodecHelperWriteByte(
245 data, (b ? FlutterStandardFieldTrue : FlutterStandardFieldFalse));
246 success = true;
247 } else if (CFNumberIsFloatType(number)) {
248 Float64 f;
249 success = CFNumberGetValue(number, kCFNumberFloat64Type, &f);
250 if (success) {
251 FlutterStandardCodecHelperWriteByte(data, FlutterStandardFieldFloat64);
252 FlutterStandardCodecHelperWriteAlignment(data, 8);
253 FlutterStandardCodecHelperWriteBytes(data, &f, 8);
254 }
255 } else if (CFNumberGetByteSize(number) <= 4) {
256 SInt32 n;
257 success = CFNumberGetValue(number, kCFNumberSInt32Type, &n);
258 if (success) {
259 FlutterStandardCodecHelperWriteByte(data, FlutterStandardFieldInt32);
260 FlutterStandardCodecHelperWriteBytes(data, &n, 4);
261 }
262 } else if (CFNumberGetByteSize(number) <= 8) {
263 SInt64 n;
264 success = CFNumberGetValue(number, kCFNumberSInt64Type, &n);
265 if (success) {
266 FlutterStandardCodecHelperWriteByte(data, FlutterStandardFieldInt64);
267 FlutterStandardCodecHelperWriteBytes(data, &n, 8);
268 }
269 }
270 return success;
271 }
272
273 // NOLINTEND(google-runtime-int)
FlutterStandardFieldInt64
@ FlutterStandardFieldInt64
Definition: FlutterStandardCodecHelper.h:22
FlutterStandardCodecHelperReadUTF8
CFStringRef FlutterStandardCodecHelperReadUTF8(unsigned long *location, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:75
FlutterStandardCodecHelperReadSize
uint32_t FlutterStandardCodecHelperReadSize(unsigned long *location, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:49
FlutterStandardFieldList
@ FlutterStandardFieldList
Definition: FlutterStandardCodecHelper.h:30
user_data
void * user_data
Definition: texture_registrar_unittests.cc:27
FlutterStandardFieldFloat64
@ FlutterStandardFieldFloat64
Definition: FlutterStandardCodecHelper.h:24
FlutterStandardCodecHelperWriteUTF8
void FlutterStandardCodecHelperWriteUTF8(CFMutableDataRef data, CFStringRef value)
Definition: FlutterStandardCodecHelper.cc:211
FlutterStandardFieldFloat32Data
@ FlutterStandardFieldFloat32Data
Definition: FlutterStandardCodecHelper.h:32
FlutterStandardCodecHelperWriteAlignment
void FlutterStandardCodecHelperWriteAlignment(CFMutableDataRef data, uint8_t alignment)
Definition: FlutterStandardCodecHelper.cc:201
FlutterStandardCodecHelperReadByte
uint8_t FlutterStandardCodecHelperReadByte(unsigned long *location, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:42
FlutterStandardFieldInt32
@ FlutterStandardFieldInt32
Definition: FlutterStandardCodecHelper.h:21
FlutterStandardCodecHelperReadValueOfType
CFTypeRef FlutterStandardCodecHelperReadValueOfType(unsigned long *location, CFDataRef data, uint8_t type, CFTypeRef(*ReadValue)(CFTypeRef), CFTypeRef(*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), CFTypeRef user_data)
Definition: FlutterStandardCodecHelper.cc:103
FlutterStandardFieldString
@ FlutterStandardFieldString
Definition: FlutterStandardCodecHelper.h:25
FlutterStandardFieldInt32Data
@ FlutterStandardFieldInt32Data
Definition: FlutterStandardCodecHelper.h:27
FlutterStandardFieldFalse
@ FlutterStandardFieldFalse
Definition: FlutterStandardCodecHelper.h:20
FlutterStandardFieldUInt8Data
@ FlutterStandardFieldUInt8Data
Definition: FlutterStandardCodecHelper.h:26
FlutterStandardCodecHelper.h
ReadDataNoCopy
static CFDataRef ReadDataNoCopy(unsigned long *location, unsigned long length, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:65
FlutterStandardFieldIsStandardType
static bool FlutterStandardFieldIsStandardType(uint8_t field)
Definition: FlutterStandardCodecHelper.h:35
FlutterStandardFieldTrue
@ FlutterStandardFieldTrue
Definition: FlutterStandardCodecHelper.h:19
FlutterStandardCodecHelperReadBytes
void FlutterStandardCodecHelperReadBytes(unsigned long *location, unsigned long length, void *destination, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:33
FlutterStandardCodecHelperWriteSize
void FlutterStandardCodecHelperWriteSize(CFMutableDataRef data, uint32_t size)
Definition: FlutterStandardCodecHelper.cc:188
FlutterStandardCodecHelperWriteNumber
bool FlutterStandardCodecHelperWriteNumber(CFMutableDataRef data, CFNumberRef number)
Definition: FlutterStandardCodecHelper.cc:239
FlutterStandardField
FlutterStandardField
Definition: FlutterStandardCodecHelper.h:17
FastReadValue
static CFTypeRef FastReadValue(unsigned long *location, CFDataRef data, CFTypeRef(*ReadValue)(CFTypeRef), CFTypeRef(*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), CFTypeRef user_data)
Definition: FlutterStandardCodecHelper.cc:87
FlutterStandardCodecHelperWriteData
void FlutterStandardCodecHelperWriteData(CFMutableDataRef data, CFDataRef value)
Definition: FlutterStandardCodecHelper.cc:232
FlutterStandardCodecHelperWriteBytes
void FlutterStandardCodecHelperWriteBytes(CFMutableDataRef data, const void *bytes, unsigned long length)
Definition: FlutterStandardCodecHelper.cc:182
FlutterStandardCodecHelperReadAlignment
void FlutterStandardCodecHelperReadAlignment(unsigned long *location, uint8_t alignment)
Definition: FlutterStandardCodecHelper.cc:18
FlutterStandardFieldNil
@ FlutterStandardFieldNil
Definition: FlutterStandardCodecHelper.h:18
FlutterStandardFieldMap
@ FlutterStandardFieldMap
Definition: FlutterStandardCodecHelper.h:31
PeekByte
static uint8_t PeekByte(unsigned long location, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:26
FlutterStandardCodecHelperWriteByte
void FlutterStandardCodecHelperWriteByte(CFMutableDataRef data, uint8_t value)
Definition: FlutterStandardCodecHelper.cc:178
FlutterStandardFieldFloat64Data
@ FlutterStandardFieldFloat64Data
Definition: FlutterStandardCodecHelper.h:29
FlutterStandardFieldInt64Data
@ FlutterStandardFieldInt64Data
Definition: FlutterStandardCodecHelper.h:28
FlutterStandardFieldIntHex
@ FlutterStandardFieldIntHex
Definition: FlutterStandardCodecHelper.h:23