Flutter iOS 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 
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);
95  *location += 1;
97  location, data, type, ReadValue, ReadTypedDataOfType, user_data);
98  } else {
99  return ReadValue(user_data);
100  }
101 }
102 
104  unsigned long* location,
105  CFDataRef data,
106  uint8_t type,
107  CFTypeRef (*ReadValue)(CFTypeRef),
108  CFTypeRef (*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef),
109  CFTypeRef user_data) {
111  switch (field) {
113  return nil;
115  return kCFBooleanTrue;
117  return kCFBooleanFalse;
119  int32_t value;
120  FlutterStandardCodecHelperReadBytes(location, 4, &value, data);
121  return CFAutorelease(
122  CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value));
123  }
125  int64_t value;
126  FlutterStandardCodecHelperReadBytes(location, 8, &value, data);
127  return CFAutorelease(
128  CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
129  }
131  Float64 value;
133  FlutterStandardCodecHelperReadBytes(location, 8, &value, data);
134  return CFAutorelease(
135  CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
136  }
139  return FlutterStandardCodecHelperReadUTF8(location, data);
145  return ReadTypedDataOfType(field, user_data);
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  }
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) {
191  } else if (size <= 0xffff) {
193  UInt16 value = (UInt16)size;
194  FlutterStandardCodecHelperWriteBytes(data, &value, 2);
195  } else {
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++) {
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);
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.resize(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);
246  success = true;
247  } else if (CFNumberIsFloatType(number)) {
248  Float64 f;
249  success = CFNumberGetValue(number, kCFNumberFloat64Type, &f);
250  if (success) {
254  }
255  } else if (CFNumberGetByteSize(number) <= 4) {
256  SInt32 n;
257  success = CFNumberGetValue(number, kCFNumberSInt32Type, &n);
258  if (success) {
261  }
262  } else if (CFNumberGetByteSize(number) <= 8) {
263  SInt64 n;
264  success = CFNumberGetValue(number, kCFNumberSInt64Type, &n);
265  if (success) {
268  }
269  }
270  return success;
271 }
272 
273 // NOLINTEND(google-runtime-int)
FlutterStandardFieldInt64
@ FlutterStandardFieldInt64
Definition: FlutterStandardCodecHelper.h:25
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:33
user_data
void * user_data
Definition: texture_registrar_unittests.cc:27
FlutterStandardFieldFloat64
@ FlutterStandardFieldFloat64
Definition: FlutterStandardCodecHelper.h:27
FlutterStandardCodecHelperWriteUTF8
void FlutterStandardCodecHelperWriteUTF8(CFMutableDataRef data, CFStringRef value)
Definition: FlutterStandardCodecHelper.cc:211
FlutterStandardFieldFloat32Data
@ FlutterStandardFieldFloat32Data
Definition: FlutterStandardCodecHelper.h:35
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:24
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:28
FlutterStandardFieldInt32Data
@ FlutterStandardFieldInt32Data
Definition: FlutterStandardCodecHelper.h:30
FlutterStandardFieldFalse
@ FlutterStandardFieldFalse
Definition: FlutterStandardCodecHelper.h:23
FlutterStandardFieldUInt8Data
@ FlutterStandardFieldUInt8Data
Definition: FlutterStandardCodecHelper.h:29
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:39
FlutterStandardFieldTrue
@ FlutterStandardFieldTrue
Definition: FlutterStandardCodecHelper.h:22
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:19
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:21
FlutterStandardFieldMap
@ FlutterStandardFieldMap
Definition: FlutterStandardCodecHelper.h:34
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:32
FlutterStandardFieldInt64Data
@ FlutterStandardFieldInt64Data
Definition: FlutterStandardCodecHelper.h:31
FlutterStandardFieldIntHex
@ FlutterStandardFieldIntHex
Definition: FlutterStandardCodecHelper.h:26