commit
b78c218af5
47 changed files with 1381 additions and 293 deletions
Binary file not shown.
@ -0,0 +1,70 @@ |
||||
import 'dart:io'; |
||||
|
||||
import 'dart_tutorial/addressbook.pb.dart'; |
||||
|
||||
// This function fills in a Person message based on user input. |
||||
Person promtForAddress() { |
||||
Person person = Person(); |
||||
|
||||
print('Enter person ID: '); |
||||
String input = stdin.readLineSync(); |
||||
person.id = int.parse(input); |
||||
|
||||
print('Enter name'); |
||||
person.name = stdin.readLineSync(); |
||||
|
||||
print('Enter email address (blank for none) : '); |
||||
String email = stdin.readLineSync(); |
||||
if (email.isNotEmpty) { |
||||
person.email = email; |
||||
} |
||||
|
||||
while (true) { |
||||
print('Enter a phone number (or leave blank to finish): '); |
||||
String number = stdin.readLineSync(); |
||||
if (number.isEmpty) break; |
||||
|
||||
Person_PhoneNumber phoneNumber = Person_PhoneNumber(); |
||||
|
||||
phoneNumber.number = number; |
||||
print('Is this a mobile, home, or work phone? '); |
||||
|
||||
String type = stdin.readLineSync(); |
||||
switch (type) { |
||||
case 'mobile': |
||||
phoneNumber.type = Person_PhoneType.MOBILE; |
||||
break; |
||||
case 'home': |
||||
phoneNumber.type = Person_PhoneType.HOME; |
||||
break; |
||||
case 'work': |
||||
phoneNumber.type = Person_PhoneType.WORK; |
||||
break; |
||||
default: |
||||
print('Unknown phone type. Using default.'); |
||||
} |
||||
person.phones.add(phoneNumber); |
||||
} |
||||
|
||||
return person; |
||||
} |
||||
|
||||
// Reads the entire address book from a file, adds one person based |
||||
// on user input, then writes it back out to the same file. |
||||
main(List<String> arguments) { |
||||
if (arguments.length != 1) { |
||||
print('Usage: add_person ADDRESS_BOOK_FILE'); |
||||
exit(-1); |
||||
} |
||||
|
||||
File file = File(arguments.first); |
||||
AddressBook addressBook; |
||||
if (!file.existsSync()) { |
||||
print('File not found. Creating new file.'); |
||||
addressBook = AddressBook(); |
||||
} else { |
||||
addressBook = AddressBook.fromBuffer(file.readAsBytesSync()); |
||||
} |
||||
addressBook.people.add(promtForAddress()); |
||||
file.writeAsBytes(addressBook.writeToBuffer()); |
||||
} |
@ -0,0 +1,47 @@ |
||||
import 'dart:io'; |
||||
|
||||
import 'dart_tutorial/addressbook.pb.dart'; |
||||
import 'dart_tutorial/addressbook.pbenum.dart'; |
||||
|
||||
// Iterates though all people in the AddressBook and prints info about them. |
||||
void printAddressBook(AddressBook addressBook) { |
||||
for (Person person in addressBook.people) { |
||||
print('Person ID: ${person.id}'); |
||||
print(' Name: ${person.name}'); |
||||
if (person.hasEmail()) { |
||||
print(' E-mail address:${person.email}'); |
||||
} |
||||
|
||||
for (Person_PhoneNumber phoneNumber in person.phones) { |
||||
switch (phoneNumber.type) { |
||||
case Person_PhoneType.MOBILE: |
||||
print(' Mobile phone #: '); |
||||
break; |
||||
case Person_PhoneType.HOME: |
||||
print(' Home phone #: '); |
||||
break; |
||||
case Person_PhoneType.WORK: |
||||
print(' Work phone #: '); |
||||
break; |
||||
default: |
||||
print(' Unknown phone #: '); |
||||
break; |
||||
} |
||||
print(phoneNumber.number); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Reads the entire address book from a file and prints all |
||||
// the information inside. |
||||
main(List<String> arguments) { |
||||
if (arguments.length != 1) { |
||||
print('Usage: list_person ADDRESS_BOOK_FILE'); |
||||
exit(-1); |
||||
} |
||||
|
||||
// Read the existing address book. |
||||
File file = new File(arguments.first); |
||||
AddressBook addressBook = new AddressBook.fromBuffer(file.readAsBytesSync()); |
||||
printAddressBook(addressBook); |
||||
} |
@ -0,0 +1,5 @@ |
||||
name: addressbook |
||||
description: dartlang.org example code. |
||||
|
||||
dependencies: |
||||
protobuf: |
@ -0,0 +1,179 @@ |
||||
#!/bin/bash |
||||
|
||||
# Updates objectivec_nsobject_methods.h by generating a list of all of the properties |
||||
# and methods on NSObject that Protobufs should not overload from iOS and macOS combined. |
||||
# |
||||
# The rules: |
||||
# - No property should ever be overloaded. |
||||
# - Do not overload any methods that have 0 args such as "autorelease". |
||||
# - Do not overload any methods that start with "set[A-Z]" and have 1 arg such as |
||||
# "setValuesForKeysWithDictionary:". Note that these will end up in the list as just |
||||
# the "proto field" name, so "setValuesForKeysWithDictionary:" will become |
||||
# "valuesForKeysWithDictionary". |
||||
|
||||
set -eu |
||||
|
||||
trim() { |
||||
local var="$*" |
||||
# remove leading whitespace characters |
||||
var="${var#"${var%%[![:space:]]*}"}" |
||||
# remove trailing whitespace characters |
||||
var="${var%"${var##*[![:space:]]}"}" |
||||
echo -n "$var" |
||||
} |
||||
|
||||
objc_code=$(cat <<'END_CODE' |
||||
#import <Foundation/Foundation.h> |
||||
#import <objc/runtime.h> |
||||
|
||||
int main(int argc, const char * argv[]) { |
||||
@autoreleasepool { |
||||
Class cls = [NSObject class]; |
||||
|
||||
// List out the protocols on NSObject just so we are aware if they change. |
||||
unsigned int protocolCount; |
||||
__unsafe_unretained Protocol **protocols = |
||||
class_copyProtocolList(cls, &protocolCount); |
||||
for (unsigned int i = 0; i < protocolCount; i++) { |
||||
printf("// Protocol: %s\n", protocol_getName(protocols[i])); |
||||
} |
||||
free(protocols); |
||||
|
||||
// Grab all the properties. |
||||
unsigned int propCount; |
||||
objc_property_t *props = class_copyPropertyList(cls, &propCount); |
||||
NSMutableSet *reservedNames = [[NSMutableSet alloc] init]; |
||||
for (unsigned int i = 0; i < propCount; ++i) { |
||||
NSString *propertyName = [NSString stringWithUTF8String:property_getName(props[i])]; |
||||
[reservedNames addObject:propertyName]; |
||||
} |
||||
free(props); |
||||
|
||||
// Note that methods have 2 defaults args (_cmd and SEL) so a method "0 arg method" |
||||
// actually has 2. |
||||
unsigned int methodCount; |
||||
Method *methods = class_copyMethodList(cls, &methodCount); |
||||
for (unsigned int i = 0; i < methodCount; ++i) { |
||||
int argCount = method_getNumberOfArguments(methods[i]); |
||||
NSString *methodName = |
||||
[NSString stringWithUTF8String:sel_getName(method_getName(methods[i]))]; |
||||
if (argCount == 2) { |
||||
[reservedNames addObject:methodName]; |
||||
} |
||||
if (argCount == 3 && [methodName hasPrefix:@"set"] && methodName.length > 4) { |
||||
NSString *firstLetter = [methodName substringWithRange:NSMakeRange(3,1)]; |
||||
NSString *lowerFirstLetter = [firstLetter lowercaseString]; |
||||
if ([lowerFirstLetter isEqual:firstLetter]) { |
||||
// Make sure the next letter is a capital letter so we do not take things like |
||||
// settingSomething: |
||||
continue; |
||||
} |
||||
// -5 because 3 for set, 1 for the firstLetter and 1 for the colon on the end. |
||||
NSString *restOfString = |
||||
[methodName substringWithRange:NSMakeRange(4, methodName.length - 5)]; |
||||
methodName = [lowerFirstLetter stringByAppendingString:restOfString]; |
||||
[reservedNames addObject:methodName]; |
||||
} |
||||
} |
||||
free(methods); |
||||
|
||||
SEL sortSelector = @selector(caseInsensitiveCompare:); |
||||
NSArray *array = [reservedNames.allObjects sortedArrayUsingSelector:sortSelector]; |
||||
for (NSString *item in array) { |
||||
// Some items with _ in them get returned in quotes, so do not add more. |
||||
if ([item hasPrefix:@"\""]) { |
||||
printf("\t%s,\n", item.UTF8String); |
||||
} else { |
||||
printf("\t\"%s\",\n", item.UTF8String); |
||||
} |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
END_CODE |
||||
) |
||||
|
||||
file_header=$(cat <<'END_HEADER' |
||||
// NSObject methods |
||||
// Autogenerated by method_dump.sh. Do not edit by hand. |
||||
// Date: %DATE% |
||||
// macOS: %MACOS% |
||||
// iOS: %IOS% |
||||
|
||||
const char* const kNSObjectMethodsList[] = { |
||||
END_HEADER |
||||
) |
||||
|
||||
file_footer=$(cat <<'END_FOOTER' |
||||
}; |
||||
END_FOOTER |
||||
) |
||||
|
||||
# Check to make sure we are updating the correct file. |
||||
if [[ ! -e "objectivec_nsobject_methods.h" ]]; then |
||||
echo "error: Must be run in the src/google/protobuf/compiler/objectivec directory" |
||||
exit 1 |
||||
fi |
||||
|
||||
temp_dir=$(mktemp -d) |
||||
|
||||
echo "$objc_code" >> "$temp_dir"/method_dump.m |
||||
|
||||
# Compile up iphonesimulator and macos version of cmd line app. |
||||
iphone_simulator_sdk=$(xcrun --sdk iphonesimulator --show-sdk-path) |
||||
clang -isysroot "$iphone_simulator_sdk" -o "$temp_dir"/method_dump_ios \ |
||||
-framework Foundation -framework UIKit "$temp_dir"/method_dump.m |
||||
macos_sdk=$(xcrun --sdk macosx --show-sdk-path) |
||||
clang -isysroot "$macos_sdk" -o "$temp_dir"/method_dump_macos -framework Foundation \ |
||||
-framework Cocoa "$temp_dir"/method_dump.m |
||||
|
||||
# Create a device of the latest phone and iphonesimulator SDK and run our iOS cmd line. |
||||
device_type=$(xcrun simctl list devicetypes | grep \.iPhone- | tail -1 | sed 's/.*(\(.*\))/\1/') |
||||
# runtimes come with a space at the end (for Xcode 10) so let's trim all of our input to |
||||
# be safe. |
||||
device_type=$(trim "$device_type") |
||||
runtime=$(xcrun simctl list runtimes | grep \.iOS- | tail -1 | \ |
||||
sed 's/.*\(com\.apple.\CoreSimulator\.SimRuntime\.iOS.*\)/\1/') |
||||
runtime=$(trim "$runtime") |
||||
uuid=$(uuidgen) |
||||
device_name="method_dump_device_$uuid" |
||||
device=$(xcrun simctl create "$device_name" "$device_type" "$runtime") |
||||
xcrun simctl spawn "$device" "$temp_dir"/method_dump_ios > "$temp_dir"/methods_unsorted_ios.txt |
||||
xcrun simctl delete "$device" |
||||
|
||||
# Run the Mac version |
||||
"$temp_dir"/method_dump_macos >> "$temp_dir"/methods_unsorted_macos.txt |
||||
|
||||
# Generate sorted output |
||||
echo "$file_header" | sed -e "s|%DATE%|$(date)|" -e "s|%MACOS%|$(basename $macos_sdk)|" \ |
||||
-e "s|%IOS%|$(basename $iphone_simulator_sdk)|" > "$temp_dir"/methods_sorted.txt |
||||
sort -u "$temp_dir"/methods_unsorted_ios.txt \ |
||||
"$temp_dir"/methods_unsorted_macos.txt >> "$temp_dir"/methods_sorted.txt |
||||
echo $"$file_footer" >> "$temp_dir"/methods_sorted.txt |
||||
|
||||
# Check for differences. Turn off error checking because we expect diff to fail when |
||||
# there are no differences. |
||||
set +e |
||||
diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h) |
||||
removed_methods=$(echo "$diff_out" | grep '^>.*$') |
||||
set -e |
||||
if [[ -n "$removed_methods" ]]; then |
||||
echo "error: Methods removed from NSObject" |
||||
echo "It appears that some methods may have been removed from NSObject." |
||||
echo "This could mean that there may be some backwards compatibility issues." |
||||
echo "You could potentially build apps that may not work on earlier systems than:" |
||||
echo "$iphone_simulator_sdk" |
||||
echo "$macos_sdk" |
||||
echo "If they declare protobuf types that use any of the following as names:" |
||||
echo "$removed_methods" |
||||
echo "" |
||||
echo "New Version: $temp_dir/methods_sorted.txt" |
||||
echo "Old Version: objectivec_nsobject_methods.h" |
||||
exit 1 |
||||
fi |
||||
if [[ -n "$diff_out" ]]; then |
||||
echo "Added Methods:" |
||||
echo "$(echo "$diff_out" | grep '^<.*$' | sed -e 's/^< "\(.*\)",$/ \1/')" |
||||
fi; |
||||
cp "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h |
||||
rm -rf "$temp_dir" |
@ -0,0 +1,197 @@ |
||||
// NSObject methods
|
||||
// Autogenerated by method_dump.sh. Do not edit by hand.
|
||||
// Date: Thu Nov 1 14:12:16 PDT 2018
|
||||
// macOS: MacOSX10.14.sdk
|
||||
// iOS: iPhoneSimulator12.1.sdk
|
||||
|
||||
const char* const kNSObjectMethodsList[] = { |
||||
"CAMLType", |
||||
"CA_copyRenderValue", |
||||
"CA_prepareRenderValue", |
||||
"NS_copyCGImage", |
||||
"NS_tiledLayerVisibleRect", |
||||
"___tryRetain_OA", |
||||
"__autorelease_OA", |
||||
"__dealloc_zombie", |
||||
"__release_OA", |
||||
"__retain_OA", |
||||
"_accessibilityFinalize", |
||||
"_accessibilityIsTableViewDescendant", |
||||
"_accessibilityUIElementSpecifier", |
||||
"_accessibilityUseConvenienceAPI", |
||||
"_allowsDirectEncoding", |
||||
"_asScriptTerminologyNameArray", |
||||
"_asScriptTerminologyNameString", |
||||
"_bindingAdaptor", |
||||
"_cfTypeID", |
||||
"_copyDescription", |
||||
"_destroyObserverList", |
||||
"_didEndKeyValueObserving", |
||||
"_implicitObservationInfo", |
||||
"_internalAccessibilityAttributedHint", |
||||
"_internalAccessibilityAttributedLabel", |
||||
"_internalAccessibilityAttributedValue", |
||||
"_isAXConnector", |
||||
"_isAccessibilityContainerSectionCandidate", |
||||
"_isAccessibilityContentNavigatorSectionCandidate", |
||||
"_isAccessibilityContentSectionCandidate", |
||||
"_isAccessibilityTopLevelNavigatorSectionCandidate", |
||||
"_isDeallocating", |
||||
"_isKVOA", |
||||
"_isToManyChangeInformation", |
||||
"_ivarDescription", |
||||
"_localClassNameForClass", |
||||
"_methodDescription", |
||||
"_observerStorage", |
||||
"_overrideUseFastBlockObservers", |
||||
"_propertyDescription", |
||||
"_releaseBindingAdaptor", |
||||
"_scriptingCount", |
||||
"_scriptingCountNonrecursively", |
||||
"_scriptingDebugDescription", |
||||
"_scriptingExists", |
||||
"_scriptingShouldCheckObjectIndexes", |
||||
"_shortMethodDescription", |
||||
"_shouldSearchChildrenForSection", |
||||
"_traitStorageList", |
||||
"_tryRetain", |
||||
"_ui_descriptionBuilder", |
||||
"_uikit_variesByTraitCollections", |
||||
"_web_description", |
||||
"_webkit_invokeOnMainThread", |
||||
"_willBeginKeyValueObserving", |
||||
"accessibilityActivate", |
||||
"accessibilityActivationPoint", |
||||
"accessibilityAllowsOverriddenAttributesWhenIgnored", |
||||
"accessibilityAssistiveTechnologyFocusedIdentifiers", |
||||
"accessibilityAttributedHint", |
||||
"accessibilityAttributedLabel", |
||||
"accessibilityAttributedValue", |
||||
"accessibilityContainer", |
||||
"accessibilityContainerType", |
||||
"accessibilityCustomActions", |
||||
"accessibilityCustomRotors", |
||||
"accessibilityDecrement", |
||||
"accessibilityDragSourceDescriptors", |
||||
"accessibilityDropPointDescriptors", |
||||
"accessibilityElementCount", |
||||
"accessibilityElementDidBecomeFocused", |
||||
"accessibilityElementDidLoseFocus", |
||||
"accessibilityElementIsFocused", |
||||
"accessibilityElements", |
||||
"accessibilityElementsHidden", |
||||
"accessibilityFrame", |
||||
"accessibilityHeaderElements", |
||||
"accessibilityHint", |
||||
"accessibilityIdentification", |
||||
"accessibilityIdentifier", |
||||
"accessibilityIncrement", |
||||
"accessibilityLabel", |
||||
"accessibilityLanguage", |
||||
"accessibilityLocalizedStringKey", |
||||
"accessibilityNavigationStyle", |
||||
"accessibilityOverriddenAttributes", |
||||
"accessibilityParameterizedAttributeNames", |
||||
"accessibilityPath", |
||||
"accessibilityPerformEscape", |
||||
"accessibilityPerformMagicTap", |
||||
"accessibilityPresenterProcessIdentifier", |
||||
"accessibilityShouldUseUniqueId", |
||||
"accessibilitySupportsNotifications", |
||||
"accessibilitySupportsOverriddenAttributes", |
||||
"accessibilityTemporaryChildren", |
||||
"accessibilityTraits", |
||||
"accessibilityValue", |
||||
"accessibilityViewIsModal", |
||||
"accessibilityVisibleArea", |
||||
"allPropertyKeys", |
||||
"allowsWeakReference", |
||||
"attributeKeys", |
||||
"autoContentAccessingProxy", |
||||
"autorelease", |
||||
"awakeFromNib", |
||||
"boolValueSafe", |
||||
"bs_encoded", |
||||
"bs_isPlistableType", |
||||
"bs_secureEncoded", |
||||
"cl_json_serializeKey", |
||||
"class", |
||||
"classCode", |
||||
"classDescription", |
||||
"classForArchiver", |
||||
"classForCoder", |
||||
"classForKeyedArchiver", |
||||
"classForPortCoder", |
||||
"className", |
||||
"clearProperties", |
||||
"copy", |
||||
"dealloc", |
||||
"debugDescription", |
||||
"defaultAccessibilityTraits", |
||||
"description", |
||||
"doubleValueSafe", |
||||
"entityName", |
||||
"exposedBindings", |
||||
"finalize", |
||||
"finishObserving", |
||||
"flushKeyBindings", |
||||
"hash", |
||||
"init", |
||||
"int64ValueSafe", |
||||
"isAccessibilityElement", |
||||
"isAccessibilityElementByDefault", |
||||
"isElementAccessibilityExposedToInterfaceBuilder", |
||||
"isFault", |
||||
"isNSArray__", |
||||
"isNSCFConstantString__", |
||||
"isNSData__", |
||||
"isNSDate__", |
||||
"isNSDictionary__", |
||||
"isNSNumber__", |
||||
"isNSObject__", |
||||
"isNSOrderedSet__", |
||||
"isNSSet__", |
||||
"isNSString__", |
||||
"isNSTimeZone__", |
||||
"isNSValue__", |
||||
"isProxy", |
||||
"mutableCopy", |
||||
"nilValueForKey", |
||||
"objectSpecifier", |
||||
"observationInfo", |
||||
"pep_onDetachedThread", |
||||
"pep_onMainThread", |
||||
"pep_onMainThreadIfNecessary", |
||||
"prepareForInterfaceBuilder", |
||||
"release", |
||||
"releaseOnMainThread", |
||||
"retain", |
||||
"retainCount", |
||||
"retainWeakReference", |
||||
"scriptingProperties", |
||||
"self", |
||||
"shouldGroupAccessibilityChildren", |
||||
"storedAccessibilityActivationPoint", |
||||
"storedAccessibilityContainerType", |
||||
"storedAccessibilityElementsHidden", |
||||
"storedAccessibilityFrame", |
||||
"storedAccessibilityNavigationStyle", |
||||
"storedAccessibilityTraits", |
||||
"storedAccessibilityViewIsModal", |
||||
"storedIsAccessibilityElement", |
||||
"storedShouldGroupAccessibilityChildren", |
||||
"stringValueSafe", |
||||
"superclass", |
||||
"toManyRelationshipKeys", |
||||
"toOneRelationshipKeys", |
||||
"traitStorageList", |
||||
"un_safeBoolValue", |
||||
"userInterfaceItemIdentifier", |
||||
"utf8ValueSafe", |
||||
"valuesForKeysWithDictionary", |
||||
"zone", |
||||
// Protocol: CAAnimatableValue
|
||||
// Protocol: CARenderValue
|
||||
// Protocol: NSObject
|
||||
// Protocol: ROCKRemoteInvocationInterface
|
||||
}; |
Loading…
Reference in new issue