This repository was archived by the owner on Feb 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6k
Sped up reading with FlutterStandardCodec. #38327
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
54407e1
Sped up reading with FlutterStandardCodec.
gaaclarke e47a555
added missing license diff
gaaclarke cf38db3
put the IsStandardType in the header so it's closer to where it shoul…
gaaclarke dad8623
added unittest for subclassing codecs
gaaclarke 175c167
fixed lints
gaaclarke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
shell/platform/darwin/common/framework/Source/FlutterStandardCodecHelper.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include "flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodecHelper.h" | ||
| #include <stdint.h> | ||
|
|
||
| void FlutterStandardCodecHelperReadAlignment(unsigned long* location, | ||
| uint8_t alignment) { | ||
| uint8_t mod = *location % alignment; | ||
| if (mod) { | ||
| *location += (alignment - mod); | ||
| } | ||
| } | ||
|
|
||
| static uint8_t PeekByte(unsigned long location, CFDataRef data) { | ||
| uint8_t result; | ||
| CFRange range = CFRangeMake(location, 1); | ||
| CFDataGetBytes(data, range, &result); | ||
| return result; | ||
| } | ||
|
|
||
| static bool IsStandardType(uint8_t type) { | ||
| switch (type) { | ||
| case FlutterStandardFieldNil: | ||
| case FlutterStandardFieldTrue: | ||
| case FlutterStandardFieldFalse: | ||
| case FlutterStandardFieldInt32: | ||
| case FlutterStandardFieldInt64: | ||
| case FlutterStandardFieldIntHex: | ||
| case FlutterStandardFieldFloat64: | ||
| case FlutterStandardFieldString: | ||
| case FlutterStandardFieldUInt8Data: | ||
| case FlutterStandardFieldInt32Data: | ||
| case FlutterStandardFieldInt64Data: | ||
| case FlutterStandardFieldFloat64Data: | ||
| case FlutterStandardFieldList: | ||
| case FlutterStandardFieldMap: | ||
| case FlutterStandardFieldFloat32Data: | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| void FlutterStandardCodecHelperReadBytes(unsigned long* location, | ||
| unsigned long length, | ||
| void* destination, | ||
| CFDataRef data) { | ||
| CFRange range = CFRangeMake(*location, length); | ||
| CFDataGetBytes(data, range, destination); | ||
| *location += length; | ||
| } | ||
|
|
||
| uint8_t FlutterStandardCodecHelperReadByte(unsigned long* location, | ||
| CFDataRef data) { | ||
| uint8_t value; | ||
| FlutterStandardCodecHelperReadBytes(location, 1, &value, data); | ||
| return value; | ||
| } | ||
|
|
||
| uint32_t FlutterStandardCodecHelperReadSize(unsigned long* location, | ||
| CFDataRef data) { | ||
| uint8_t byte = FlutterStandardCodecHelperReadByte(location, data); | ||
| if (byte < 254) { | ||
| return (uint32_t)byte; | ||
| } else if (byte == 254) { | ||
| UInt16 value; | ||
| FlutterStandardCodecHelperReadBytes(location, 2, &value, data); | ||
| return value; | ||
| } else { | ||
| UInt32 value; | ||
| FlutterStandardCodecHelperReadBytes(location, 4, &value, data); | ||
| return value; | ||
| } | ||
| } | ||
|
|
||
| static CFDataRef ReadDataNoCopy(unsigned long* location, | ||
| unsigned long length, | ||
| CFDataRef data) { | ||
| CFDataRef result = CFDataCreateWithBytesNoCopy( | ||
| kCFAllocatorDefault, CFDataGetBytePtr(data) + *location, length, | ||
| kCFAllocatorNull); | ||
| *location += length; | ||
| return CFAutorelease(result); | ||
| } | ||
|
|
||
| CFStringRef FlutterStandardCodecHelperReadUTF8(unsigned long* location, | ||
| CFDataRef data) { | ||
| uint32_t size = FlutterStandardCodecHelperReadSize(location, data); | ||
| CFDataRef bytes = ReadDataNoCopy(location, size, data); | ||
| CFStringRef result = CFStringCreateFromExternalRepresentation( | ||
| kCFAllocatorDefault, bytes, kCFStringEncodingUTF8); | ||
| return CFAutorelease(result); | ||
| } | ||
|
|
||
| // Peeks ahead to see if we are reading a standard type. If so, recurse | ||
| // directly to FlutterStandardCodecHelperReadValueOfType, otherwise recurse to | ||
| // objc. | ||
| static inline CFTypeRef FastReadValue( | ||
| unsigned long* location, | ||
| CFDataRef data, | ||
| CFTypeRef (*ReadValue)(CFTypeRef), | ||
| CFTypeRef (*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), | ||
| CFTypeRef user_data) { | ||
| uint8_t type = PeekByte(*location, data); | ||
| if (IsStandardType(type)) { | ||
| *location += 1; | ||
| return FlutterStandardCodecHelperReadValueOfType( | ||
| location, data, type, ReadValue, ReadTypedDataOfType, user_data); | ||
| } else { | ||
| return ReadValue(user_data); | ||
| } | ||
| } | ||
|
||
|
|
||
| CFTypeRef FlutterStandardCodecHelperReadValueOfType( | ||
| unsigned long* location, | ||
| CFDataRef data, | ||
| uint8_t type, | ||
| CFTypeRef (*ReadValue)(CFTypeRef), | ||
| CFTypeRef (*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), | ||
| CFTypeRef user_data) { | ||
| FlutterStandardField field = (FlutterStandardField)type; | ||
| switch (field) { | ||
| case FlutterStandardFieldNil: | ||
| return nil; | ||
| case FlutterStandardFieldTrue: | ||
| return kCFBooleanTrue; | ||
| case FlutterStandardFieldFalse: | ||
| return kCFBooleanFalse; | ||
| case FlutterStandardFieldInt32: { | ||
| int32_t value; | ||
| FlutterStandardCodecHelperReadBytes(location, 4, &value, data); | ||
| return CFAutorelease( | ||
| CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value)); | ||
| } | ||
| case FlutterStandardFieldInt64: { | ||
| int64_t value; | ||
| FlutterStandardCodecHelperReadBytes(location, 8, &value, data); | ||
| return CFAutorelease( | ||
| CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value)); | ||
| } | ||
| case FlutterStandardFieldFloat64: { | ||
| Float64 value; | ||
| FlutterStandardCodecHelperReadAlignment(location, 8); | ||
| FlutterStandardCodecHelperReadBytes(location, 8, &value, data); | ||
| return CFAutorelease( | ||
| CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); | ||
| } | ||
| case FlutterStandardFieldIntHex: | ||
| case FlutterStandardFieldString: | ||
| return FlutterStandardCodecHelperReadUTF8(location, data); | ||
| case FlutterStandardFieldUInt8Data: | ||
| case FlutterStandardFieldInt32Data: | ||
| case FlutterStandardFieldInt64Data: | ||
| case FlutterStandardFieldFloat32Data: | ||
| case FlutterStandardFieldFloat64Data: | ||
| return ReadTypedDataOfType(field, user_data); | ||
| case FlutterStandardFieldList: { | ||
| UInt32 length = FlutterStandardCodecHelperReadSize(location, data); | ||
| CFMutableArrayRef array = CFArrayCreateMutable( | ||
| kCFAllocatorDefault, length, &kCFTypeArrayCallBacks); | ||
| for (UInt32 i = 0; i < length; i++) { | ||
| CFTypeRef value = FastReadValue(location, data, ReadValue, | ||
| ReadTypedDataOfType, user_data); | ||
| CFArrayAppendValue(array, (value == nil ? kCFNull : value)); | ||
| } | ||
| return CFAutorelease(array); | ||
| } | ||
| case FlutterStandardFieldMap: { | ||
| UInt32 size = FlutterStandardCodecHelperReadSize(location, data); | ||
| CFMutableDictionaryRef dict = CFDictionaryCreateMutable( | ||
| kCFAllocatorDefault, size, &kCFTypeDictionaryKeyCallBacks, | ||
| &kCFTypeDictionaryValueCallBacks); | ||
| for (UInt32 i = 0; i < size; i++) { | ||
| CFTypeRef key = FastReadValue(location, data, ReadValue, | ||
| ReadTypedDataOfType, user_data); | ||
| CFTypeRef val = FastReadValue(location, data, ReadValue, | ||
| ReadTypedDataOfType, user_data); | ||
| CFDictionaryAddValue(dict, (key == nil ? kCFNull : key), | ||
| (val == nil ? kCFNull : val)); | ||
| } | ||
| return CFAutorelease(dict); | ||
| } | ||
| default: | ||
| // Malformed message. | ||
| assert(false); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember exactly, does the compiler warn you if a new enum is added and a case is not handled in the switch statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point is this might cause mistakes if a new enum is added and this code is not updated. If there is no compiler warning, maybe we can add a comment, or use a different way to determine valid enums.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the check to be right next to the enum declaration and added a comment that it needs to be updated if it changes.