@@ -211,114 +211,144 @@ - (instancetype)initWithData:(NSMutableData*)data {
211211}
212212
213213- (void )writeByte : (UInt8)value {
214- [ _data appendBytes: & value length: 1 ] ;
214+ FlutterStandardCodecHelperWriteByte ((__bridge CFMutableDataRef) _data, value) ;
215215}
216216
217217- (void )writeBytes : (const void *)bytes length : (NSUInteger )length {
218- [ _data appendBytes: bytes length: length] ;
218+ FlutterStandardCodecHelperWriteBytes ((__bridge CFMutableDataRef) _data, bytes, length) ;
219219}
220220
221221- (void )writeData : (NSData *)data {
222- [ _data appendData: data] ;
222+ FlutterStandardCodecHelperWriteData ((__bridge CFMutableDataRef) _data, (__bridge CFDataRef) data) ;
223223}
224224
225225- (void )writeSize : (UInt32)size {
226- if (size < 254 ) {
227- [self writeByte: (UInt8)size];
228- } else if (size <= 0xffff ) {
229- [self writeByte: 254 ];
230- UInt16 value = (UInt16)size;
231- [self writeBytes: &value length: 2 ];
232- } else {
233- [self writeByte: 255 ];
234- [self writeBytes: &size length: 4 ];
235- }
226+ FlutterStandardCodecHelperWriteSize ((__bridge CFMutableDataRef)_data, size);
236227}
237228
238229- (void )writeAlignment : (UInt8)alignment {
239- UInt8 mod = _data.length % alignment;
240- if (mod) {
241- for (int i = 0 ; i < (alignment - mod); i++) {
242- [self writeByte: 0 ];
243- }
244- }
230+ FlutterStandardCodecHelperWriteAlignment ((__bridge CFMutableDataRef)_data, alignment);
245231}
246232
247233- (void )writeUTF8 : (NSString *)value {
248- UInt32 length = [value lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
249- [self writeSize: length];
250- [self writeBytes: value.UTF8String length: length];
234+ FlutterStandardCodecHelperWriteUTF8 ((__bridge CFMutableDataRef)_data,
235+ (__bridge CFStringRef)value);
251236}
252237
253- - ( void ) writeValue : ( id ) value {
254- if (value == nil || value == [ NSNull null ] ) {
255- [ self writeByte: FlutterStandardFieldNil] ;
238+ static FlutterStandardCodecObjcType GetWriteType ( id value) {
239+ if (value == nil || (__bridge CFNullRef) value == kCFNull ) {
240+ return FlutterStandardCodecObjcTypeNil ;
256241 } else if ([value isKindOfClass: [NSNumber class ]]) {
257- CFNumberRef number = (__bridge CFNumberRef)value;
258- BOOL success = NO ;
259- if (CFGetTypeID (number) == CFBooleanGetTypeID ()) {
260- BOOL b = CFBooleanGetValue ((CFBooleanRef)number);
261- [self writeByte: (b ? FlutterStandardFieldTrue : FlutterStandardFieldFalse)];
262- success = YES ;
263- } else if (CFNumberIsFloatType (number)) {
264- Float64 f;
265- success = CFNumberGetValue (number, kCFNumberFloat64Type , &f);
266- if (success) {
267- [self writeByte: FlutterStandardFieldFloat64];
268- [self writeAlignment: 8 ];
269- [self writeBytes: (UInt8*)&f length: 8 ];
270- }
271- } else if (CFNumberGetByteSize (number) <= 4 ) {
272- SInt32 n;
273- success = CFNumberGetValue (number, kCFNumberSInt32Type , &n);
274- if (success) {
275- [self writeByte: FlutterStandardFieldInt32];
276- [self writeBytes: (UInt8*)&n length: 4 ];
277- }
278- } else if (CFNumberGetByteSize (number) <= 8 ) {
279- SInt64 n;
280- success = CFNumberGetValue (number, kCFNumberSInt64Type , &n);
281- if (success) {
282- [self writeByte: FlutterStandardFieldInt64];
283- [self writeBytes: (UInt8*)&n length: 8 ];
284- }
285- }
286- if (!success) {
287- NSLog (@" Unsupported value: %@ of number type %ld " , value, CFNumberGetType(number));
288- NSAssert (NO , @" Unsupported value for standard codec" );
289- }
242+ return FlutterStandardCodecObjcTypeNSNumber;
290243 } else if ([value isKindOfClass: [NSString class ]]) {
291- NSString * string = value;
292- [self writeByte: FlutterStandardFieldString];
293- [self writeUTF8: string];
244+ return FlutterStandardCodecObjcTypeNSString;
294245 } else if ([value isKindOfClass: [FlutterStandardTypedData class ]]) {
295- FlutterStandardTypedData* typedData = value;
296- [self writeByte: FlutterStandardFieldForDataType (typedData.type)];
297- [self writeSize: typedData.elementCount];
298- [self writeAlignment: typedData.elementSize];
299- [self writeData: typedData.data];
246+ return FlutterStandardCodecObjcTypeFlutterStandardTypedData;
300247 } else if ([value isKindOfClass: [NSData class ]]) {
301- [ self writeValue: [FlutterStandardTypedData typedDataWithBytes: value]] ;
248+ return FlutterStandardCodecObjcTypeNSData ;
302249 } else if ([value isKindOfClass: [NSArray class ]]) {
303- NSArray * array = value;
304- [self writeByte: FlutterStandardFieldList];
305- [self writeSize: array.count];
306- for (id object in array) {
307- [self writeValue: object];
308- }
250+ return FlutterStandardCodecObjcTypeNSArray;
309251 } else if ([value isKindOfClass: [NSDictionary class ]]) {
310- NSDictionary * dict = value;
311- [self writeByte: FlutterStandardFieldMap];
312- [self writeSize: dict.count];
313- for (id key in dict) {
314- [self writeValue: key];
315- [self writeValue: [dict objectForKey: key]];
316- }
252+ return FlutterStandardCodecObjcTypeNSDictionary;
317253 } else {
318- NSLog (@" Unsupported value: %@ of type %@ " , value, [value class ]);
319- NSAssert (NO , @" Unsupported value for standard codec" );
254+ return FlutterStandardCodecObjcTypeUnknown;
320255 }
321256}
257+
258+ struct WriteKeyValuesInfo {
259+ CFTypeRef writer;
260+ CFMutableDataRef data;
261+ };
262+
263+ static void WriteKeyValues (CFTypeRef key, CFTypeRef value, void * context) {
264+ WriteKeyValuesInfo* info = (WriteKeyValuesInfo*)context;
265+ FastWriteValueOfType (info->writer , info->data , key);
266+ FastWriteValueOfType (info->writer , info->data , value);
267+ }
268+
269+ // Recurses into WriteValueOfType directly if it is writing a known type,
270+ // otherwise recurses with objc_msgSend.
271+ static void FastWriteValueOfType (CFTypeRef writer, CFMutableDataRef data, CFTypeRef value) {
272+ FlutterStandardCodecObjcType type = GetWriteType ((__bridge id )value);
273+ if (type != FlutterStandardCodecObjcTypeUnknown) {
274+ WriteValueOfType (writer, data, type, value);
275+ } else {
276+ [(__bridge FlutterStandardWriter*)writer writeValue: (__bridge id )value];
277+ }
278+ }
279+
280+ static void WriteValueOfType (CFTypeRef writer,
281+ CFMutableDataRef data,
282+ FlutterStandardCodecObjcType type,
283+ CFTypeRef value) {
284+ switch (type) {
285+ case FlutterStandardCodecObjcTypeNil:
286+ FlutterStandardCodecHelperWriteByte (data, FlutterStandardFieldNil);
287+ break ;
288+ case FlutterStandardCodecObjcTypeNSNumber: {
289+ CFNumberRef number = (CFNumberRef)value;
290+ BOOL success = FlutterStandardCodecHelperWriteNumber (data, number);
291+ if (!success) {
292+ NSLog (@" Unsupported value: %@ of number type %ld " , value, CFNumberGetType(number));
293+ NSCAssert (NO , @" Unsupported value for standard codec" );
294+ }
295+ break ;
296+ }
297+ case FlutterStandardCodecObjcTypeNSString: {
298+ CFStringRef string = (CFStringRef)value;
299+ FlutterStandardCodecHelperWriteByte (data, FlutterStandardFieldString);
300+ FlutterStandardCodecHelperWriteUTF8 (data, string);
301+ break ;
302+ }
303+ case FlutterStandardCodecObjcTypeFlutterStandardTypedData: {
304+ FlutterStandardTypedData* typedData = (__bridge FlutterStandardTypedData*)value;
305+ FlutterStandardCodecHelperWriteByte (data, FlutterStandardFieldForDataType (typedData.type ));
306+ FlutterStandardCodecHelperWriteSize (data, typedData.elementCount );
307+ FlutterStandardCodecHelperWriteAlignment (data, typedData.elementSize );
308+ FlutterStandardCodecHelperWriteData (data, (__bridge CFDataRef)typedData.data );
309+ break ;
310+ }
311+ case FlutterStandardCodecObjcTypeNSData:
312+ WriteValueOfType (writer, data, FlutterStandardCodecObjcTypeFlutterStandardTypedData,
313+ (__bridge CFTypeRef)
314+ [FlutterStandardTypedData typedDataWithBytes: (__bridge NSData *)value]);
315+ break ;
316+ case FlutterStandardCodecObjcTypeNSArray: {
317+ CFArrayRef array = (CFArrayRef)value;
318+ FlutterStandardCodecHelperWriteByte (data, FlutterStandardFieldList);
319+ CFIndex count = CFArrayGetCount (array);
320+ FlutterStandardCodecHelperWriteSize (data, count);
321+ for (CFIndex i = 0 ; i < count; ++i) {
322+ FastWriteValueOfType (writer, data, CFArrayGetValueAtIndex (array, i));
323+ }
324+ break ;
325+ }
326+ case FlutterStandardCodecObjcTypeNSDictionary: {
327+ CFDictionaryRef dict = (CFDictionaryRef)value;
328+ FlutterStandardCodecHelperWriteByte (data, FlutterStandardFieldMap);
329+ CFIndex count = CFDictionaryGetCount (dict);
330+ FlutterStandardCodecHelperWriteSize (data, count);
331+ WriteKeyValuesInfo info = {
332+ .writer = writer,
333+ .data = data,
334+ };
335+ CFDictionaryApplyFunction (dict, WriteKeyValues, (void *)&info);
336+ break ;
337+ }
338+ case FlutterStandardCodecObjcTypeUnknown: {
339+ id objc_value = (__bridge id )value;
340+ NSLog (@" Unsupported value: %@ of type %@ " , objc_value, [objc_value class ]);
341+ NSCAssert (NO , @" Unsupported value for standard codec" );
342+ break ;
343+ }
344+ }
345+ }
346+
347+ - (void )writeValue : (id )value {
348+ FlutterStandardCodecObjcType type = GetWriteType (value);
349+ WriteValueOfType ((__bridge CFTypeRef)self, (__bridge CFMutableDataRef)self->_data , type,
350+ (__bridge CFTypeRef)value);
351+ }
322352@end
323353
324354@implementation FlutterStandardReader {
0 commit comments